sipeed/picoclaw · error
parsing device code response: %w
Error message
parsing device code response: %w
What it means
Thrown by RequestDeviceCode (pkg/auth/oauth.go:276) when the POST to {Issuer}/api/accounts/deviceauth/usercode returned HTTP 200 but parseDeviceCodeResponse could not decode the body. The parser expects JSON with device_auth_id, user_code and an interval that is a number, numeric string, or null; any JSON decode failure or a bad interval type propagates here.
Source
Thrown at pkg/auth/oauth.go:276
"application/json",
strings.NewReader(string(reqBody)),
)
if err != nil {
return nil, fmt.Errorf("requesting device code: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("reading device code response: %w", err)
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("device code request failed: %s", string(body))
}
deviceResp, err := parseDeviceCodeResponse(body)
if err != nil {
return nil, fmt.Errorf("parsing device code response: %w", err)
}
if deviceResp.Interval < 1 {
deviceResp.Interval = 5
}
return &DeviceCodeInfo{
DeviceAuthID: deviceResp.DeviceAuthID,
UserCode: deviceResp.UserCode,
VerifyURL: cfg.Issuer + "/codex/device",
Interval: deviceResp.Interval,
}, nil
}
// PollDeviceCodeOnce makes a single poll attempt to check if the user has authenticated.
// Returns (credential, nil) on success, (nil, nil) if still pending, or (nil, err) on failure.
func PollDeviceCodeOnce(cfg OAuthProviderConfig, deviceAuthID, userCode string) (*AuthCredential, error) {
return pollDeviceCode(cfg, deviceAuthID, userCode)View on GitHub (pinned to 49183d7e8d)
Solutions
- Curl the exact endpoint to inspect the payload: curl -sS -X POST -H 'Content-Type: application/json' -d '{"client_id":"..."}' $ISSUER/api/accounts/deviceauth/usercode
- Verify cfg.Issuer is the OAuth issuer root (e.g. https://auth.openai.com) with no trailing slash, path, or /v1 suffix
- Check the interval field type in the response: must be a number, numeric string, or null (not float/bool/object)
- If the provider API changed shape, update parseDeviceCodeResponse field tags or the endpoint path in pkg/auth/oauth.go
- Log the raw body next to the parse error so future failures show what the server actually returned
Example fix
// before
deviceResp, err := parseDeviceCodeResponse(body)
if err != nil {
return nil, fmt.Errorf("parsing device code response: %w", err)
}
// after (include raw body for diagnosis, truncated)
deviceResp, err := parseDeviceCodeResponse(body)
if err != nil {
snippet := body
if len(snippet) > 512 {
snippet = snippet[:512]
}
return nil, fmt.Errorf("parsing device code response: %w (body: %s)", err, snippet)
} Defensive patterns
Strategy: try-catch
Validate before calling
// Validate issuer shape before the call
if u, err := url.Parse(cfg.Issuer); err != nil || u.Scheme == "" || u.Host == "" {
return fmt.Errorf("invalid issuer URL: %q", cfg.Issuer)
} Type guard
func isDeviceCodeParseError(err error) bool {
return err != nil && strings.Contains(err.Error(), "parsing device code response")
} Try / catch
info, err := auth.RequestDeviceCode(cfg)
if err != nil {
if isDeviceCodeParseError(err) {
// log issuer and endpoint; likely schema/issuer mismatch — do not blind-retry
log.Printf("device code schema mismatch from %s: %v", cfg.Issuer, err)
}
return err
} Prevention
- Pin the expected issuer root in config validation
- Add a contract test that fixtures match parseDeviceCodeResponse's expected JSON keys
- Include the response body in parse-failure logs
- Fail config load when Issuer lacks scheme/host instead of letting HTTP/JSON errors surface later
When it happens
Trigger: Calling RequestDeviceCode(cfg) where the issuer endpoint replies 200 with: malformed JSON, HTML instead of JSON, missing/mis-typed fields (e.g. interval as 5.5, true, or an object), or an unexpected API envelope that fails json.Unmarshal/parseFlexibleInt.
Common situations: Issuer base URL misconfigured to a host that serves a 200 status page; a corporate proxy or captive portal injecting HTML; the provider renaming fields or shipping a new device-auth API version; middleware returning an empty 200 body.
Related errors
- invalid integer value: %s
- parsing token response: %w
- failed to unmarshal response: %w
- device code authentication timed out after 15 minutes
- reading device token response: %w
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/0f0886919a4d28d9.
Report an issue: GitHub.