{"record":{"id":"969de6e4a97910ae","repo":"sipeed/picoclaw","slug":"failed-to-generate-state-v","errorCode":null,"errorMessage":"failed to generate state: %v","messagePattern":"failed to generate state: (.+?)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"critical","filePath":"web/backend/api/oauth.go","lineNumber":284,"sourceCode":"\t\t\t\"expires_at\": flow.ExpiresAt.Format(time.RFC3339),\n\t\t})\n\t\treturn\n\n\tcase oauthMethodBrowser:\n\t\tcfg, err := oauthConfigForProvider(provider)\n\t\tif err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\n\t\tpkce, err := oauthGeneratePKCE()\n\t\tif err != nil {\n\t\t\thttp.Error(w, fmt.Sprintf(\"failed to generate PKCE: %v\", err), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t\tstate, err := oauthGenerateState()\n\t\tif err != nil {\n\t\t\thttp.Error(w, fmt.Sprintf(\"failed to generate state: %v\", err), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\n\t\tredirectURI := buildOAuthRedirectURI(r)\n\t\tauthURL := oauthBuildAuthorizeURL(cfg, pkce, state, redirectURI)\n\n\t\tnow := oauthNow()\n\t\tflow := &oauthFlow{\n\t\t\tID:           newOAuthFlowID(),\n\t\t\tProvider:     provider,\n\t\t\tMethod:       method,\n\t\t\tStatus:       oauthFlowPending,\n\t\t\tCreatedAt:    now,\n\t\t\tUpdatedAt:    now,\n\t\t\tExpiresAt:    now.Add(oauthBrowserFlowTTL),\n\t\t\tCodeVerifier: pkce.CodeVerifier,\n\t\t\tOAuthState:   state,\n\t\t\tRedirectURI:  redirectURI,","sourceCodeStart":266,"sourceCodeEnd":302,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/web/backend/api/oauth.go#L266-L302","documentation":"Returned as HTTP 500 by POST /api/oauthLogin (browser method) when auth.GenerateState fails. GenerateState reads 32 bytes from crypto/rand and hex-encodes them; like the PKCE failure, it only fails when the system CSPRNG is inaccessible. It is the same class of environmental failure as error 966, one call later in the same handler.","triggerScenarios":"POST /api/oauth/login {\"provider\":\"openai\",\"method\":\"browser\"} on a runtime where crypto/rand.Read errors (seccomp-blocked getrandom, early-boot entropy starvation, broken /dev/urandom). If PKCE succeeded but this fails, the entropy source died between the two calls.","commonSituations":"Hardened container runtimes, VMs without RNG devices, chroot environments without /dev mounted properly.","solutions":["Test the CSPRNG in the backend's exact environment (a Go one-liner with crypto/rand or reading /dev/urandom).","Fix the sandbox/kernel (allow getrandom, add virtio-rng to the VM, mount /dev properly) and retry the browser login.","Treat repeated occurrences as an infrastructure incident: this error means the host cannot generate secure randomness at all, which breaks every auth path, not just this one.","Workaround for users: complete login with method \"token\" if available for the provider (openai, anthropic)."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"const res = await startBrowserLogin(provider);\nif (res.status === 500 && /generate state/i.test((await res.json()).message ?? '')) {\n  return startTokenLogin(provider); // CSPRNG unavailable — use a method that needs no rand\n}\nreturn res;","preventionTips":["Same class as PKCE failure: check the runtime can read /dev/urandom before deploying browser login.","Give VMs an RNG device (virtio-rng) so entropy is available at boot.","Alert on this error: a broken CSPRNG undermines every auth flow on the host."],"tags":["oauth","http-500","state","crypto-rand","environment"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}