Skip to content

Exit with distinct statuses for not found, auth and unavailable - #295

Merged
schpetbot merged 1 commit into
mainfrom
schpet/push-twnqqqrwlxqp
Oct 6, 2026
Merged

schpetbot merged 1 commit into
mainfrom
schpet/push-twnqqqrwlxqp

Conversation

@schpetbot

Copy link
Copy Markdown
Collaborator

Every runtime failure exited 1, so a script couldn't tell a revoked key from a missing issue without parsing stderr. Failures now carry a class on the error, set where the evidence is structured (request classification, credential selection, entity lookups) and kept through .context():

status meaning
0 success
1 any other failure, including GraphQL errors such as an invalid query
2 usage error (unchanged)
3 not found: an issue, team, or other entity the command looked up
4 authentication: no usable API key, or Linear rejected it (401/403, AUTHENTICATION_ERROR)
5 unavailable: network failure, timeout, HTTP 408/429/5xx, or Linear's RATELIMITED (which comes with HTTP 400)
130 cancelled (unchanged)

The issue's table, re-run against real Linear with this build:

command bad key unreachable missing issue
linear api '{ viewer { name } }' 4 5
linear issue view … 4 5 3
linear api '{ issue(id: "ZZZ-99999") { id } }' 3
linear api '{ nope }' 1

How this differs from the suggestion in the issue:

  • 4 is auth and 3 is not found, not the other way round, to match gh (4 = authentication required), which agents already know.
  • "network" became "unavailable". Scripts mainly need to know whether retrying later can help, and that covers 5xx and rate limiting too. The docs warn that a create or update that exits 5 may still have taken effect.
  • Not-found can't hide an auth failure. Each GraphQL error is classified on its own and the most serious wins. Not-found detection now matches only Linear's own wording (Entity not found… / Could not find referenced…).
  • linear api classifies its response the same way, and its local input mistakes (no query, bad --variables-json) are now usage errors (2).
  • Bulk commands exit with the most serious class among their items (4 > 5 > 1 > 3), and say items "could not be found" only when every skipped item really was missing.

Documented in linear --help, the README, docs/usage.md, the agent skill, and the CHANGELOG's "Upgrading from 2.x" exit-codes entry.

Fixes #293

Every runtime failure exited 1, so a script could not tell a revoked key
from a missing issue without parsing stderr. Failures now carry a class
on the error itself, set where the evidence is structured (request
classification, credential selection, entity lookups) and kept through
context: 3 not found, 4 authentication, 5 unavailable (network, timeout,
HTTP 408/429/5xx, Linear's RATELIMITED code, which comes with HTTP 400),
1 for everything else, alongside the existing 2 and 130.

The report suggested 3 auth / 4 not found / 5 network. Two independent
designs both chose 4 for authentication to match `gh`, and broadened
"network" to "unavailable" since the question a script asks is whether
retrying later can help. Beyond the literal report: a missing entity
next to an authentication error is no longer treated as "not found"
(each GraphQL error is classified and the most serious wins, and the
not-found check now only matches Linear's own wording); `linear api`
classifies its response the same way, and its local input errors are
usage errors; bulk commands exit with the most serious class among their
items (4 > 5 > 1 > 3) and only say "could not be found" when every
skipped item was missing. The statuses are listed in `linear --help`,
the README, the usage docs and the agent skill.

Github-Issue: Fixes #293
Github-Issue-Url: #293
@schpetbot
schpetbot merged commit 9f671af into main Oct 6, 2026
10 checks passed
@schpetbot
schpetbot deleted the schpet/push-twnqqqrwlxqp branch October 6, 2026 14:43
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.

Distinguish failure classes in the exit status (auth, not found, network)

2 participants