The db OpenAPI collapses every dataloom business failure into one of two numeric
codes by the first digit of the upstream 7-digit code, so a dozen unrelated
states share code 400002476 and the specific reason survives only as a
`k_dl_<digits>` prefix on the message. Classifying on the numeric code therefore
cannot distinguish them, and all of these surfaced as subtype "unknown" with a
per-command hint that described the wrong problem — enabling audit on a
multi-env app's online branch was advised to "verify --app-id and --table", both
of which are correct, and an import whose cell value did not fit its column type
read as a server-side failure worth retrying when only the file can be fixed.
Classify on the subcode instead, keyed on the subcode string rather than on
where it was read from, so exposing it as a structured field later changes only
the extraction step. Six subcodes observed on the wire are mapped; unmapped ones
keep today's behaviour and their prefix, which is the only remaining clue for a
case the CLI does not know.
Turning table audit on or off also makes the server initialize the app's
data-sync task under a workspace-wide lock, and a concurrent holder is reported
as a failure rather than waited for. That specific failure is now retried a
bounded number of times with jittered backoff, and the wait honours the command
context so a cancelled command cannot issue another audit write. Safe to repeat,
unlike writes in general: the server rolls its own changelog write back before
returning, so a contended call leaves audit off rather than half-applied, and a
repeat either succeeds or reports "already enabled".
Matching requires the lock marker as well as the subcode, because that subcode
covers a second cause — a sync task stuck in a terminal state — which repeating
the call does not resolve. The two are kept apart all the way to what the caller
sees: contention is reported as a collision with a concurrent request and marked
retryable, while the unrecognised variant keeps neutral wording and no retryable
flag. Only contention has been observed to clear on its own, and promising
otherwise would walk an agent through a round of attempts that cannot work
against a write endpoint.
The numeric code is left as the server reported it, since the troubleshooter URL
in the same envelope is keyed on it. Message falls back to per-entry wording when
the server sends a subcode with no text: assigning the empty remainder would
blank Message, which errs.Problem requires and whose absence makes Error()
return "".