{"record":{"id":"351965c7c918f551","repo":"hashicorp/nomad","slug":"error-storing-oidc-request-w","errorCode":null,"errorMessage":"error storing OIDC request: %w","messagePattern":"error storing OIDC request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/auth/oidc/request.go","lineNumber":97,"sourceCode":"\treturn nil\n}\n\n// LoadOrAdd atomically fetches a previously cached oidc.Req or creates once\n// using the provided function and stores it before returning it. If\n// LoadAndDelete is not called later, the stale request will eventually expire\n// and be auto-deleted.\nfunc (rc *RequestCache) LoadOrAdd(clientNonce string, create func() (*oidc.Req, error)) (*oidc.Req, error) {\n\trc.lock.Lock()\n\tdefer rc.lock.Unlock()\n\tvar err error\n\toidcReq := rc.loadLocked(clientNonce)\n\tif oidcReq == nil {\n\t\toidcReq, err = create()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif err = rc.storeLocked(oidcReq); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error storing OIDC request: %w\", err)\n\t\t}\n\t}\n\treturn oidcReq, nil\n}\n\n// LoadAndDelete atomically loads a previously-cache oidc.Req and clears it from\n// the cache\nfunc (rc *RequestCache) LoadAndDelete(nonce string) *oidc.Req {\n\trc.lock.Lock()\n\tdefer rc.lock.Unlock()\n\tif req, ok := rc.c.Get(nonce); ok {\n\t\trc.c.Remove(nonce)\n\t\treturn req\n\t}\n\treturn nil\n}\n","sourceCodeStart":79,"sourceCodeEnd":114,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/lib/auth/oidc/request.go#L79-L114","documentation":"LoadOrAdd atomically loads a cached oidc request or creates one via create(); after creating, it persists the request with storeLocked. This error wraps any failure from that store write (e.g. backend connection failure, serialization error, lock contention). The OIDC request could not be cached, so the auth flow aborts.","triggerScenarios":"OIDCAuthURL or cacheOIDCRequest calls LoadOrAdd, the request is not yet cached (cache miss), create() succeeds, but rc.storeLocked writes to the backing store fails — Redis/consul store down, timeout, or lock acquisition failure.","commonSituations":"Backend cache service unreachable or restarted mid-flow; network partition between Nomad and the state store; store size limits rejecting the serialized request; expired/lost distributed lock.","solutions":["Check connectivity and health of the backing state store (e.g. redis/consul endpoint in config)","Inspect the wrapped error (%w) for the root cause — timeout vs connection refused vs serialization","Retry the OIDC auth URL generation; the failure is typically transient","If persistent, verify store credentials, size limits, and lock configuration"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Pre-check store reachability before starting the OIDC flow\nif err := store.Ping(ctx); err != nil {\n\treturn fmt.Errorf(\"OIDC request store unreachable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"oidcReq, err := cache.LoadOrAdd(ctx, key, create)\nif err != nil {\n\tif strings.Contains(err.Error(), \"error storing OIDC request\") {\n\t\t// inspect wrapped cause; transient store failure — retry with backoff\n\t\treturn retryWithBackoff(func() error {\n\t\t\t_, err := cache.LoadOrAdd(ctx, key, create)\n\t\t\treturn err\n\t\t})\n\t}\n\treturn err\n}","preventionTips":["Monitor the backing state store's health and alerts","Set sane store timeouts and connection-pool limits","Keep serialized OIDC requests small to avoid store size limits","Retry idempotent LoadOrAdd calls on transient store errors"],"tags":["oidc","cache","storage","network"],"backgroundTag":"state-store-write-failed","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}