← Community
bugopen

`str(exception)[:140]` truncates a receipt's only failure diagnostic well below a reasonable message length, sometimes mid-word

Muhammad Akif JanjuaMuhammad Akif Janjua#41d ago · 6 views
affected: station-v1.5.8

Reproduction steps:

  1. Have a module handler raise a RuntimeError with a legitimately informative

message longer than 140 characters — for example, Notion Guard's own
multi-data-source rejection: "This database has 3 data sources; pass one
explicitly via data_source_id: <uuid1>, <uuid2>, <uuid3>" (204 characters
with a realistic 3-entry list).

  1. routes/commands.py's exception handler builds

note = "execution failed: " + str(e)[:140].

  1. Verified concretely (not just in theory) with the actual message text:

full message length: 204
truncated to 140 (Station note field):
execution failed: This database has 3 data sources; pass one explicitly via
data_source_id: 1f2e3d4c-5b6a-7980-9c8d-0e1f2a3b4c5d, 2a3b4c5d-6
The truncation lands mid-UUID, mid-way through the second of three IDs.

Expected: A receipt's failure diagnostic should preserve enough of a well-
behaved handler's error message to be independently useful during audit —
at minimum, not truncate a bounded, already-capped message body mid-token.

Actual: The 140-character cap is well below what a reasonably-bounded
handler message can be — Notion Guard's own _extract_error_message caps at
300 characters, a limit chosen deliberately to keep messages useful while
bounded. Station's outer cap is under half of that, and it isn't content-
aware (doesn't stop at a token/word boundary), so it can and does cut a
message off mid-UUID, mid-word, anywhere.

Root cause: note="execution failed: " + str(e)[:140] in routes/commands.py's
exception handler is a flat character slice with no boundary awareness and
no consideration of what a well-formed handler message actually needs to
convey. 140 was likely chosen as "short enough to keep receipts compact"
without accounting for legitimately-informative multi-part error messages
(lists of IDs, multiple validation failures, etc.).

Suggested fix: Either raise the cap to something closer to what modules are
reasonably expected to produce (e.g. 280-320 characters, matching the kind
of budget a well-behaved handler like this one already self-imposes), or
truncate on a word boundary with an explicit "…" marker so a reader can tell
the note was cut rather than assuming it's complete. The safer of the two is
raising the cap — boundary-aware truncation still loses the same
information, just less confusingly.

Impact: Anyone reconstructing what happened from a receipt alone — the
entire point of a signed, independently-verifiable audit trail — can be
handed a truncated, sometimes unusable fragment of the actual failure reason
(e.g. a partially-cut UUID they can't act on) for any command whose
legitimate error message runs long. This weakens the audit trail's core
promise on exactly the failure cases where a full explanation matters most.

0 replies

Sign in to reply.