You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
cli: reclassify non-envelope errors and split 401/403 auth codes (#205)
Route error responses with no v3 envelope through FromAPIError by HTTP status
instead of the opaque `error` code: 4xx map to client codes, 5xx to
unclassified_server_error, unmapped to unclassified_client_error, always with a
non-empty message. Preserve code-only envelopes (relaxed the message-only gate).
Split 401/403 into unauthorized/forbidden so a 403 no longer suggests logging in;
enrichAuthHint is gated to not-authenticated codes. Help footer + README exit-code
table now read '3 auth/permission'.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: README.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -165,7 +165,7 @@ Every command supports `--help`.
165
165
|--------|----------|
166
166
|**stdout**| Always JSON. Even `video download` — binary writes to disk; stdout emits `{"asset", "message", "path"}` so you can chain on `.path`. |
167
167
|**stderr**| Structured envelope on error: `{"error": {"code", "message", "hint"}}`. Stable `code` values for programmatic branching. |
168
-
|**Exit codes**|`0` ok · `1` API or network · `2` usage · `3` auth · `4` timeout under `--wait` (stdout contains partial resource for resume) |
168
+
|**Exit codes**|`0` ok · `1` API or network · `2` usage · `3` auth / not permitted · `4` timeout under `--wait` (stdout contains partial resource for resume) |
169
169
|**Request bodies**| Flags for simple inputs; `-d` for nested JSON (inline, file path, or `-` for stdin). Flags override matching fields. |
170
170
|**Async jobs**|`--wait` blocks with exponential backoff; `--timeout` sets max (default 20m). 429s and 5xx retry automatically. |
// isNonSpecific reports whether an API-provided error code is too generic to
79
+
// trust for classification. v3 always sends a specific code; an empty or literal
80
+
// "error" code means we should classify from the HTTP status instead.
81
+
funcisNonSpecific(codestring) bool {
82
+
returncode==""||code=="error"
83
+
}
84
+
85
+
// forbiddenHint is the shared non-login guidance for 403 responses: the caller is
86
+
// authenticated but not permitted, so re-authenticating will not help.
87
+
constforbiddenHint="Your credentials are valid but not permitted for this. Check your plan, permissions, or workspace — re-authenticating will not help. Contact support if this is unexpected."
88
+
78
89
// FromAPIError converts an API error envelope and HTTP status code into a CLIError.
90
+
//
91
+
// The v3 API always returns a specific lowercase code, which is preserved. When the
92
+
// code is absent or non-specific (empty or literal "error" — e.g. a non-envelope
93
+
// edge/gateway response routed here by parseErrorResponse), the code is derived from
0 commit comments