Skip to main content
← Back to list
01Issue
BugShippedSwamp CLIPublic
Assigneesskunk-ape

Relationships

#2279 issue-lifecycle: lifecycle entries whose payload contains a quote-dollar sequence are rejected 422/400 and the failure is swallowed

Opened by skunk-ape · 9/18/2026· Shipped 9/18/2026

Found while triaging swamp-club#2265.

What happened

Running the triage method on issue 2265 with a reasoning string that quoted a shell snippet produced:

swamp-club lifecycle post failed: 400 {"error":"payload keys must not start with $"}

The method still reported "Completed ... succeeded" and advanced the local phase to classified. Upstream, updateType and transitionStatus both landed (type=bug, status=triaged), but the classified lifecycle entry - the one carrying the full triage reasoning - was never recorded. The triage rationale was silently lost.

Cause

Two separate defects compose.

  1. Server-side validator appears to be naive. None of the payload keys constructed in extensions/models/issue_lifecycle.ts around line 923 start with a dollar sign - they are fixed literals (type, confidence, reasoning, isRegression, ...). The only dollar sign anywhere in the request was inside a string VALUE: the reasoning text quoted a shell comparison, which serialises into the JSON body as a double-quote character immediately followed by a dollar sign. That two-character sequence looks like the start of a dollar-prefixed key to a validator scanning the serialised body rather than walking the parsed object. Removing the dollar sign from the reasoning text and re-running made the identical call succeed, which confirms the trigger.

  2. postLifecycleEntry swallows the failure. extensions/models/_lib/swamp_club.ts lines 154-191: the method is documented "Best-effort" - on a non-ok response it logs and returns normally. The caller cannot distinguish a recorded entry from a dropped one, so the method reports success either way.

A related swallow fires on the same path: re-running triage against an already-triaged issue logs

swamp-club patch failed: 422 {"error":"Cannot triage issue in status \"triaged\". Expected \"open\"."}

and likewise reports success.

Why it matters

This is the same "missing signal read as success" shape that swamp-club#2265 documents in the verification harness, and that the patchIssue swallow showed earlier. The lifecycle record in swamp-club is the audit trail for triage, planning, approval and attestation. An entry that silently fails to post leaves the upstream history incomplete while every local signal says the step succeeded.

Suggested fix

  • Server: validate dollar-prefixed keys by walking the parsed object, not by scanning the serialised body, so ordinary prose and code snippets in string values are not rejected.
  • Client: stop swallowing. Either surface a non-ok lifecycle post as a method failure, or return a status the caller checks and reports. At minimum the step should not print "succeeded" when the upstream record was not written.
  • Treat the 422 already-in-target-status case as benign explicitly rather than lumping it in with real failures.

Reproduction

Run any issue-lifecycle method whose payload includes a string value containing a double-quote immediately followed by a dollar sign. The post returns 400 and the method reports success.

02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED+ 1 MOREASSIGNED+ 14 MOREREVIEW+ 7 MOREPR_MERGED+ 2 MORESESSION_SUMMARIZED

Shipped

9/18/2026, 9:20:56 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
skunk-ape assigned skunk-ape9/18/2026, 5:46:21 PM

Sign in to post a ripple.