Repository navigation
Persist status code and cause on provider error events (#674) #882
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
1d3e263
8f712b6
c762013
08e6a61
ef00dd6
031b841
ba92df9
571675d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,46 @@ | ||||||
| package sessions | ||||||
|
|
||||||
| import ( | ||||||
| "errors" | ||||||
|
|
||||||
| "github.com/Gitlawb/zero/internal/zeroruntime" | ||||||
| ) | ||||||
|
|
||||||
| // maxErrorCauseBytes bounds the persisted cause. Provider error bodies are read | ||||||
| // up to 64 KiB, which is far more than a diagnostic needs and would otherwise be | ||||||
| // copied whole into every error event in events.jsonl. | ||||||
| const maxErrorCauseBytes = 8 << 10 | ||||||
|
|
||||||
| const errorCauseTruncationMarker = "… [truncated]" | ||||||
|
|
||||||
| // ErrorEventPayload builds the payload for an EventError session event. It | ||||||
| // always includes the flattened message (unchanged, for backward | ||||||
| // compatibility with existing consumers of events.jsonl), and additionally | ||||||
| // persists the HTTP status code and upstream cause when err is (or wraps) a | ||||||
| // *zeroruntime.StreamError — the structured error a failed provider stream | ||||||
| // returns. Without this, a provider error left no way to diagnose *why* a | ||||||
| // call failed from the CLI or its logs — only the generic top-level message | ||||||
| // was ever recorded (#674). Cause has already been redacted for secrets by | ||||||
| // the provider before reaching here (see zeroruntime.StreamEvent.Cause) — it | ||||||
| // is never re-scrubbed or stored raw at this layer. Cause is cut to | ||||||
| // maxErrorCauseBytes (on a rune boundary) with a truncation marker appended. | ||||||
| func ErrorEventPayload(err error) map[string]any { | ||||||
| payload := map[string]any{"message": err.Error()} | ||||||
| var streamErr *zeroruntime.StreamError | ||||||
| if errors.As(err, &streamErr) { | ||||||
| if streamErr.StatusCode != 0 { | ||||||
| payload["statusCode"] = streamErr.StatusCode | ||||||
| } | ||||||
| if streamErr.Cause != "" { | ||||||
| payload["cause"] = boundErrorCause(streamErr.Cause) | ||||||
| } | ||||||
| } | ||||||
| return payload | ||||||
| } | ||||||
|
|
||||||
| func boundErrorCause(cause string) string { | ||||||
| if len(cause) <= maxErrorCauseBytes { | ||||||
| return cause | ||||||
| } | ||||||
| return truncateUTF8(cause, maxErrorCauseBytes) + errorCauseTruncationMarker | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: sed -n '1,85p' internal/sessions/error_payload.go
sed -n '125,165p' internal/sessions/error_payload_test.go
rg -n 'maxErrorCauseBytes|errorCauseTruncationMarker|8 KiB|8KiB' internal/sessionsRepository: Twigpine/zero Length of output: 4370 🏁 Script executed: set -e
printf '%s\n' '--- truncateUTF8 definitions and callers ---'
rg -n -F -- 'func truncateUTF8' .
rg -n -F -- 'truncateUTF8(' internal
printf '%s\n' '--- error payload tests ---'
sed -n '1,190p' internal/sessions/error_payload_test.go
printf '%s\n' '--- helper context ---'
rg -n -F -C 8 -- 'func truncateUTF8' internal
printf '%s\n' '--- base-to-head diff for the relevant files ---'
git diff --unified=30 99721c762f37cd43ac511007a5f51d1846df959e3 571675db9ceda30a12d57dc252ffefe21d2319d3 -- internal/sessions/error_payload.go internal/sessions/error_payload_test.goRepository: Twigpine/zero Length of output: 15646 Keep the persisted cause within the 8 KiB cap. For an oversized 🐛 Suggested fix--- "a/internal/sessions/error_payload.go"
+++ "b/internal/sessions/error_payload.go"
@@ -42,5 +42,5 @@
if len(cause) <= maxErrorCauseBytes {
return cause
}
- return truncateUTF8(cause, maxErrorCauseBytes) + errorCauseTruncationMarker
+ return truncateUTF8(cause, maxErrorCauseBytes-len(errorCauseTruncationMarker)) + errorCauseTruncationMarker
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| } | ||||||
Uh oh!
There was an error while loading. Please reload this page.