From 824db0036e23eb068e3d652c93b3462ecb8a8e3c Mon Sep 17 00:00:00 2001 From: Ian Duffy Date: Thu, 5 Nov 2026 10:43:30 +0000 Subject: [PATCH 1/2] fix(no-ticket): do not report an input/output error from the terminal When the terminal closes or the SSH session drops while a command runs, the next write to stdout or stderr fails with OSError EIO. The error reached AliasGroup.main, and the CLI sent it to Sentry as a crash. Treat EIO as a device error in is_reportable. The CLI still shows the error and exits with status 1. Fixes CLOUDSMITH-CLI-2B Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 1 + cloudsmith_cli/core/telemetry.py | 3 +++ cloudsmith_cli/core/tests/test_telemetry.py | 9 +++++++++ 3 files changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38ed7fb3e..5f9ba1a17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -84,6 +84,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - When the CLI waits before it retries a failed connection or a 5xx response, it now writes `Request failed: retrying in N second(s) ...` to stderr. Previously, it waited without output. - The CLI now exits with status 1 when you interrupt it with Ctrl+C after the reader of its stderr has closed the pipe. Before, the CLI sent an error report and exited with status 120. - `cloudsmith check rates` no longer stops with `TypeError` when the API does not give a value for an interval, limit, remaining count, reset time or throttled status. The command now shows `None` for that value. +- The CLI no longer sends an error report when a write fails with an input/output error (EIO). For example, this occurs when the terminal closes or the SSH session drops while a command runs. The CLI still shows the error and exits with status 1. ## [1.30.0] - 2026-10-22 diff --git a/cloudsmith_cli/core/telemetry.py b/cloudsmith_cli/core/telemetry.py index 50adac798..35f3a9424 100644 --- a/cloudsmith_cli/core/telemetry.py +++ b/cloudsmith_cli/core/telemetry.py @@ -22,6 +22,7 @@ ``sentry_sdk`` must only ever be imported inside :func:`_send`. """ +import errno import os import platform import re @@ -149,10 +150,12 @@ def is_reportable(exc: BaseException) -> bool: ``report_to_telemetry = False``. Checked by attribute rather than by importing the types, so this module stays light on the error path. A failed TLS certificate check is a problem with the network, not with the CLI. + An EIO error comes from the device, such as a terminal that hung up. """ return ( getattr(exc, REPORTABLE_ATTR, True) is not False and find_certificate_error(exc) is None + and not (isinstance(exc, OSError) and exc.errno == errno.EIO) ) diff --git a/cloudsmith_cli/core/tests/test_telemetry.py b/cloudsmith_cli/core/tests/test_telemetry.py index 3d1536a41..73a9cda46 100644 --- a/cloudsmith_cli/core/tests/test_telemetry.py +++ b/cloudsmith_cli/core/tests/test_telemetry.py @@ -1,5 +1,6 @@ """Tests for error reporting: opt-out controls, sending, and anonymisation.""" +import errno import importlib.util import json import socket @@ -154,6 +155,14 @@ class SpecificUserError(UserError): assert sentry_events == [] +def test_device_io_errors_are_not_reported(sentry_events): + """A terminal that hangs up mid-command fails the next write with EIO.""" + exc = raise_and_catch(OSError(errno.EIO, "Input/output error")) + + assert telemetry.report_exception(exc) is False + assert sentry_events == [] + + def test_exceptions_are_reportable_by_default(): assert telemetry.is_reportable(RuntimeError("boom")) is True From ca9841cbec52105ecdc4ed1f9cb96053044510c7 Mon Sep 17 00:00:00 2001 From: Ian Duffy Date: Thu, 5 Nov 2026 11:11:38 +0000 Subject: [PATCH 2/2] fix(no-ticket): do not promise an exit status for an EIO error The change only stops the error report. The exit status after a failed write to a closed terminal depends on the platform. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f9ba1a17..4a36af42f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -84,7 +84,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - When the CLI waits before it retries a failed connection or a 5xx response, it now writes `Request failed: retrying in N second(s) ...` to stderr. Previously, it waited without output. - The CLI now exits with status 1 when you interrupt it with Ctrl+C after the reader of its stderr has closed the pipe. Before, the CLI sent an error report and exited with status 120. - `cloudsmith check rates` no longer stops with `TypeError` when the API does not give a value for an interval, limit, remaining count, reset time or throttled status. The command now shows `None` for that value. -- The CLI no longer sends an error report when a write fails with an input/output error (EIO). For example, this occurs when the terminal closes or the SSH session drops while a command runs. The CLI still shows the error and exits with status 1. +- The CLI no longer sends an error report when a write fails with an input/output error (EIO). For example, this occurs when the terminal closes or the SSH session drops while a command runs. The CLI handles the error in the same way as before. ## [1.30.0] - 2026-10-22