chenhg5/cc-connect · error
decode %s response: %w
Error message
decode %s response: %w
What it means
Returned when the app-server's JSON-RPC result for a request cannot be unmarshaled into the caller-provided `out` value: `fmt.Errorf("decode %s response: %w", method, err)`. This indicates the response shape does not match the expected Go struct — usually a codex protocol version change rather than a runtime failure.
Source
Thrown at agent/codex/appserver_session.go:1646
remaining := time.Until(deadline)
if remaining <= 0 {
s.pendingMu.Lock()
delete(s.pending, id)
s.pendingMu.Unlock()
return fmt.Errorf("%s timed out", method)
}
timer := time.NewTimer(remaining)
defer timer.Stop()
ctxDone := s.contextDone()
select {
case resp := <-ch:
if resp.Error != nil {
return fmt.Errorf("%s", strings.TrimSpace(resp.Error.Message))
}
if out != nil {
if err := json.Unmarshal(resp.Result, out); err != nil {
return fmt.Errorf("decode %s response: %w", method, err)
}
}
return nil
case <-ctxDone:
return s.contextErr()
case <-timer.C:
s.pendingMu.Lock()
delete(s.pending, id)
s.pendingMu.Unlock()
return fmt.Errorf("%s timed out", method)
}
}
func (s *appServerSession) writeJSONWithTimeout(method string, v any, timeout time.Duration) error {
done := make(chan error, 1)
go func() {
done <- s.writeJSON(v)
}()View on GitHub (pinned to 4000b2338a)
Solutions
- Pin/upgrade cc-connect to a version matching your installed codex CLI version.
- Log `string(resp.Result)` for the failing method to compare actual vs expected schema.
- Check that the `out` argument passed to `request()` matches the method's documented response type.
- Downgrade codex if you must stay on the current cc-connect release.
- Handle null results defensively by decoding into json.RawMessage first.
Example fix
// before: assume old schema
var out threadStartResponse
s.request("thread/start", params, &out)
// after: inspect raw payload when decoding fails
var raw json.RawMessage
if err := s.request("thread/start", params, &raw); err != nil { ... }
slog.Debug("codex raw response", "body", string(raw)) Defensive patterns
Strategy: type-guard
Validate before calling
// decode into RawMessage first to detect shape drift
var raw json.RawMessage
if err := sess.request("thread/start", params, &raw); err != nil { return err }
var probe map[string]json.RawMessage
return json.Unmarshal(raw, &probe) // inspect keys before strict decode Type guard
func decodeAs[T any](raw json.RawMessage) (*T, error) {
var v T
if err := json.Unmarshal(raw, &v); err != nil {
return nil, fmt.Errorf("schema mismatch: %w", err)
}
return &v, nil
} Try / catch
if err := json.Unmarshal(resp.Result, out); err != nil {
slog.Error("codex response schema drift", "method", method, "body", string(resp.Result))
return fmt.Errorf("decode %s response: %w", method, err)
} Prevention
- Upgrade cc-connect whenever you upgrade codex CLI.
- Snapshot real responses in tests to catch schema drift.
- Log raw response bodies on decode failure.
- Use lenient types (json.RawMessage, pointers) for evolving fields.
When it happens
Trigger: A successful (non-error) JSON-RPC response arrives but `json.Unmarshal(resp.Result, out)` fails — e.g. field type changed, new schema, null where a struct is expected, or a wrong `out` type passed by the caller.
Common situations: Codex CLI upgraded and response fields renamed/retyped; decoding into the wrong struct for the method; server returning null result for methods expected to return objects; proxy/middleware mangling the response JSON.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
- codex app-server encode: %w
- %s decode response: %w
- parse auth.json: %w
- decode usage response: %w
- session.create decode: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/9576a8103b60ac78.
Report an issue: GitHub.