Skip to content

Exit 124 when --timeout expires resolving a data source name - #47

Merged
178inaba merged 2 commits into
mainfrom
fix/43-data-source-lookup-timeout
Aug 24, 2026
Merged

Exit 124 when --timeout expires resolving a data source name#47
178inaba merged 2 commits into
mainfrom
fix/43-data-source-lookup-timeout

Conversation

@178inaba

Copy link
Copy Markdown
Owner

Why

--timeout expiry is supposed to exit 124, and skills/rdsh/SKILL.md maps that code to "re-run with
a longer --timeout" while 1 means "a longer timeout will not help". One request escaped that mapping.

resolveDataSource turns a --data-source name into an ID by calling GET /api/data_sources, and
returned its error unwrapped; runRun and runQueryCreate passed it straight out. A deadline that
expired during the lookup therefore exited 1 with a bare context deadline exceeded — pointing an
agent away from the one recovery that would have worked. It was the only server call in internal/cmd
that missed timeoutOr by omission; the one other unwrapped call, query create's publish step, skips
it deliberately.

The result was that the same command answered differently depending only on whether --data-source was
given an ID or a name, and that the same endpoint was a timeout under rdsh data-source list and an
ordinary failure under rdsh run. This is not a corner reserved for callers who type a name: rdsh auth login prompts for a default data source by ID or name and stores the answer verbatim, so for a profile
whose default is a name, every rdsh run goes through this lookup.

This changes an exit code: a run that exits 1 today exits 124 after this change. CLAUDE.md
holds the exit codes to a higher bar than a human-facing CLI would, so it is worth stating rather than
letting it pass as an internal detail. The definition of 124 is untouched, and the new code is the one
README.md and skills/rdsh/SKILL.md already promise for this failure — the code was what disagreed
with them, which is why this is a bug fix rather than a documented promise being changed.

What

  • runRun and runQueryCreate pass resolveDataSource's error through timeoutOr(err, timeout, "the data source lookup"). The operation name reads distinctly against data-source list's the data source listing and run's own query.
  • resolveDataSource's doc comment now states that resolving a name is a server call and that callers
    wrap what it returns, so the obligation sits next to the function rather than being copied into both
    call sites.
  • Tests: the new 124 path for both commands, plus a pin that an all-digit --data-source still sends
    no listing request and still reports its expiry as the query's.

Only the deadline changes classification. timeoutOr passes anything that is not
context.DeadlineExceeded through untouched, so a name the server does not have still exits 1 with the
existing data source %q not found message, and a missing data source still exits 1 telling the caller
to pass --data-source.

Alternative considered

Mapping context.DeadlineExceeded to 124 centrally, the way the sibling CLIs do in their own
internal/cmd/root.go, is the stronger design against this class of bug in general. It is not right for
rdsh: abandonJob (internal/redash/redash.go) derives its own 10 s cancellation timeout from
context.Background() and joins that path's error with the run's, so a central errors.Is would also
fire for a cancellation that timed out — a failure the caller cannot fix by raising --timeout.
Wrapping per call site keeps the opt-in property #28 settled on, and is what #43 recommends.

Not in scope

  • data-source list, auth login, query update / list / show — all already wrapped, all untouched.
  • query create's publish step, which reports a deadline as an ordinary failure on purpose: 124 would
    tell an agent to re-run, and re-running create saves a second query.
  • README.md and skills/rdsh/SKILL.md, which already describe the behaviour this PR implements.

Verification

go test -race ./...
docker compose run --rm lint

Closes #43

The name lookup was the one server call in internal/cmd that returned its
error unwrapped by omission, so a --timeout expiry there exited 1 with a
bare context error — the code documented as "a longer timeout will not
help" — while the same endpoint under data-source list exited 124.
The buffered reached channel drops arrivals once it is full, so reading
the absence of a request out of it took a paragraph of reasoning about
which arrivals cannot be the dropped ones. The other endpoints already
answer "did this arrive" with a field set under the mutex.
@178inaba 178inaba self-assigned this Aug 24, 2026
@178inaba
178inaba merged commit 0dd65ed into main Aug 24, 2026
2 checks passed
@178inaba
178inaba deleted the fix/43-data-source-lookup-timeout branch August 24, 2026 16:11
@daemon-bot daemon-bot Bot mentioned this pull request Aug 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Exit 124 when --timeout expires resolving a data source name

1 participant