sipeed/picoclaw · critical
failed to generate PKCE: %v
Error message
failed to generate PKCE: %v
What it means
Returned as HTTP 500 by POST /api/oauth/login (browser method) when auth.GeneratePKCE fails. GeneratePKCE does a single crypto/rand.Read of 64 bytes and builds the PKCE verifier/challenge; on Linux it fails only when the kernel CSPRNG is unavailable (getrandom(2) error), which is essentially a broken or massively restricted runtime. No input from the request can cause it.
Source
Thrown at web/backend/api/oauth.go:279
"method": method,
"flow_id": flow.ID,
"user_code": flow.UserCode,
"verify_url": flow.VerifyURL,
"interval": flow.Interval,
"expires_at": flow.ExpiresAt.Format(time.RFC3339),
})
return
case oauthMethodBrowser:
cfg, err := oauthConfigForProvider(provider)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
pkce, err := oauthGeneratePKCE()
if err != nil {
http.Error(w, fmt.Sprintf("failed to generate PKCE: %v", err), http.StatusInternalServerError)
return
}
state, err := oauthGenerateState()
if err != nil {
http.Error(w, fmt.Sprintf("failed to generate state: %v", err), http.StatusInternalServerError)
return
}
redirectURI := buildOAuthRedirectURI(r)
authURL := oauthBuildAuthorizeURL(cfg, pkce, state, redirectURI)
now := oauthNow()
flow := &oauthFlow{
ID: newOAuthFlowID(),
Provider: provider,
Method: method,
Status: oauthFlowPending,
CreatedAt: now,View on GitHub (pinned to 49183d7e8d)
Solutions
- Verify the CSPRNG from inside the same environment: head -c 32 /dev/urandom | xxd (or a tiny Go program doing crypto/rand.Read).
- Loosen the container/sandbox profile so getrandom(2)//dev/urandom is permitted.
- On VMs that boot before entropy init, ensure the VM has virtio-rng or wait a few seconds after boot and retry the login request.
- If the environment fundamentally cannot provide a CSPRNG, use token login instead (method "token"), which does not call rand during the request.
Example fix
// before: sandbox blocks getrandom
POST /api/oauth/login {"provider":"openai","method":"browser"}
// -> 500 failed to generate PKCE: crypto/rand failed
// after: docker run --security-opt seccomp=unconfined ... # or fix the profile to allow getrandom
POST /api/oauth/login {"provider":"openai","method":"browser"}
// -> 200 {"auth_url":"https://auth.openai.com/..."} Defensive patterns
Strategy: fallback
Try / catch
const res = await startBrowserLogin(provider);
if (res.status === 500) {
const { message } = await res.json();
if (/generate PKCE/i.test(message ?? '')) {
// host CSPRNG is broken: fall back to token login (no randomness needed per request)
return startTokenLogin(provider);
}
throw new Error(message);
} Prevention
- Verify crypto randomness works in the deployment environment before enabling browser OAuth (head -c 32 /dev/urandom).
- Do not over-restrict container seccomp profiles — getrandom(2) must be allowed.
- Treat PKCE/state generation failures as infrastructure alerts, not user errors.
When it happens
Trigger: POST /api/oauth/login {"provider":"openai","method":"browser"} on a host where crypto/rand.Read returns an error — e.g. a seccomp/container profile blocking getrandom, an extremely early-boot VM before the entropy pool is initialized, or a broken /dev/urandom.
Common situations: Over-restrictive gVisor/Firecracker/seccomp sandboxes; exotic embedded kernels; virtually never on normal Linux/macOS dev machines or standard Docker.
Related errors
- failed to generate state: %v
- token exchange failed: %s
- credential: failed to generate salt: %w
- token login failed: %v
- failed to request device code: %v
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/9bcd5ca692a5f1ae.
Report an issue: GitHub.