sipeed/picoclaw · error
requesting device code: %w
Error message
requesting device code: %w
What it means
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).
Source
Thrown at pkg/auth/oauth.go:262
UserCode string `json:"user_code"`
VerifyURL string `json:"verify_url"`
Interval int `json:"interval"`
}
// RequestDeviceCode requests a device code from the OAuth provider.
// Returns the info needed for the user to authenticate in a browser.
func RequestDeviceCode(cfg OAuthProviderConfig) (*DeviceCodeInfo, error) {
reqBody, _ := json.Marshal(map[string]string{
"client_id": cfg.ClientID,
})
resp, err := http.Post(
cfg.Issuer+"/api/accounts/deviceauth/usercode",
"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 = 5View on GitHub (pinned to 49183d7e8d)
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
Example fix
// before: issuer from a different provider's docs cfg.Issuer = "https://accounts.google.com/o/oauth2/v2" // after: issuer that actually serves the device-auth path cfg.Issuer = "https://accounts.pico.ltd" // must expose /api/accounts/deviceauth/usercode
Defensive patterns
Strategy: retry
Validate before calling
// confirm the device-auth endpoint is reachable before starting the flow
func deviceEndpointReachable(issuer string) error {
u := issuer + "/api/accounts/deviceauth/usercode"
resp, err := http.Post(u, "application/json", strings.NewReader("{}"))
if err != nil { return fmt.Errorf("unreachable: %w", err) }
_ = resp.Body.Close()
return nil // any HTTP answer means transport is fine
} Try / catch
err := retryN(2, time.Second, func() error {
_, e := auth.RequestDeviceCode(cfg)
if e != nil && strings.Contains(e.Error(), "requesting device code") {
return e // transport-level: retry
}
return retryStop{e}
}) Prevention
- 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)
When it happens
Trigger: 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.
Common situations: Air-gapped or proxied CI environments; cfg.Issuer copied from a different provider's docs; corporate MITM CA not in the trust store.
Related errors
- device code request failed: %s
- Failed to load config
- Failed to fetch config
- fetch models: %w
- reading device code response: %w
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/4fe07a811c8753c4.
Report an issue: GitHub.