Skip to main content

Bug fixes

Notes CLI traceback regression (issue #883) The try/except around the Modal .remote(...) dispatch in cli/attio/notes.py caught only (RuntimeError, TypeError, ValidationError). The exceptions the deployed functions actually raise — AttioError subclasses (a stale --email that matches no person, a partial update whose original note could not be deleted) and the SDKError family from the Attio SDK, which Modal re-raises unwrapped in the caller’s process — are none of those three, so every routine, expected failure dumped a raw Python traceback instead of the one-line Error: ... on stderr the CLI contract describes (CLI contract). The narrowing landed in a repo-wide mechanical BLE001 lint pass (cebf36b) that was treated as non-reviewable; the pre-narrowing except Exception printed the clean line, as the sibling gtm attio companies commands still do. The handler now catches AttioError and SDKError alongside the original three, with a deliberate carve-out: the AttioError subclasses that signal a developer or deployment problem — ConfigurationError, ConnectivityError, DeploymentMismatchError — re-raise so a developer keeps the traceback a fix needs; masking them behind a one-line error is the same trap as masking Modal’s own NotFoundError or AuthError. Programming bugs (AttributeError and friends) and the Modal deserialize-fallback ExecutionError likewise stay developer-visible. The routine-vs-config taxonomy lives in the adapter (libs/attio/errors.py, is_routine_attio_error) and reaches the CLI through the src.edge facade, so the closed orchestration boundary stays intact.
Last modified on October 2, 2026