{"record":{"id":"4fe07a811c8753c4","repo":"sipeed/picoclaw","slug":"requesting-device-code-w","errorCode":null,"errorMessage":"requesting device code: %w","messagePattern":"requesting device code: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/auth/oauth.go","lineNumber":262,"sourceCode":"\tUserCode     string `json:\"user_code\"`\n\tVerifyURL    string `json:\"verify_url\"`\n\tInterval     int    `json:\"interval\"`\n}\n\n// RequestDeviceCode requests a device code from the OAuth provider.\n// Returns the info needed for the user to authenticate in a browser.\nfunc RequestDeviceCode(cfg OAuthProviderConfig) (*DeviceCodeInfo, error) {\n\treqBody, _ := json.Marshal(map[string]string{\n\t\t\"client_id\": cfg.ClientID,\n\t})\n\n\tresp, err := http.Post(\n\t\tcfg.Issuer+\"/api/accounts/deviceauth/usercode\",\n\t\t\"application/json\",\n\t\tstrings.NewReader(string(reqBody)),\n\t)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"requesting device code: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"reading device code response: %w\", err)\n\t}\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"device code request failed: %s\", string(body))\n\t}\n\n\tdeviceResp, err := parseDeviceCodeResponse(body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"parsing device code response: %w\", err)\n\t}\n\n\tif deviceResp.Interval < 1 {\n\t\tdeviceResp.Interval = 5","sourceCodeStart":244,"sourceCodeEnd":280,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/auth/oauth.go#L244-L280","documentation":"http.Post to {cfg.Issuer}/api/accounts/deviceauth/usercode failed at the transport level (oauth.go:262). No HTTP response was received: DNS resolution failed, TCP connect failed, TLS handshake failed, or the request timed out. Note the URL is the picoclaw/z.ai-style device-auth path — pointing cfg.Issuer at a standard OAuth issuer (e.g. Google) will never serve it (that surfaces as error 359 with a 404 body, not this one).","triggerScenarios":"Calling RequestDeviceCode with no internet; DNS for cfg.Issuer failing; self-signed/wrong CA blocking TLS; HTTP(S)_PROXY env routing the request into a dead proxy; Issuer with a trailing slash or typo producing an unresolvable host.","commonSituations":"Air-gapped or proxied CI environments; cfg.Issuer copied from a different provider's docs; corporate MITM CA not in the trust store.","solutions":["Reproduce the transport call: curl -v -X POST <Issuer>/api/accounts/deviceauth/usercode -H 'Content-Type: application/json' -d '{\"client_id\":\"...\"}'","Fix DNS/proxy: verify the host resolves and HTTP(S)_PROXY points at a live proxy, or unset it","Check cfg.Issuer spelling and scheme (no trailing slash, correct host)","If TLS is the issue, install the corporate CA into the system trust store"],"exampleFix":"// before: issuer from a different provider's docs\ncfg.Issuer = \"https://accounts.google.com/o/oauth2/v2\"\n\n// after: issuer that actually serves the device-auth path\ncfg.Issuer = \"https://accounts.pico.ltd\" // must expose /api/accounts/deviceauth/usercode","handlingStrategy":"retry","validationCode":"// confirm the device-auth endpoint is reachable before starting the flow\nfunc deviceEndpointReachable(issuer string) error {\n    u := issuer + \"/api/accounts/deviceauth/usercode\"\n    resp, err := http.Post(u, \"application/json\", strings.NewReader(\"{}\"))\n    if err != nil { return fmt.Errorf(\"unreachable: %w\", err) }\n    _ = resp.Body.Close()\n    return nil // any HTTP answer means transport is fine\n}","typeGuard":null,"tryCatchPattern":"err := retryN(2, time.Second, func() error {\n    _, e := auth.RequestDeviceCode(cfg)\n    if e != nil && strings.Contains(e.Error(), \"requesting device code\") {\n        return e // transport-level: retry\n    }\n    return retryStop{e}\n})","preventionTips":["Verify cfg.Issuer hosts /api/accounts/deviceauth/usercode before shipping","Check DNS/proxy reachability of the issuer before starting device flow","Distinguish this (no response) from error 359 (server refused with status)"],"tags":["network","oauth","device-flow","http","config"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}