{"record":{"id":"b5993b2a7bc3fd56","repo":"gofiber/fiber","slug":"failed-to-lock-w","errorCode":null,"errorMessage":"failed to lock: %w","messagePattern":"failed to lock: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"middleware/idempotency/idempotency.go","lineNumber":126,"sourceCode":"\t\tif c.Get(cfg.KeyHeader) == \"\" {\n\t\t\treturn c.Next()\n\t\t}\n\n\t\t// Validate key\n\t\tkey := utils.CopyString(c.Get(cfg.KeyHeader))\n\t\tif err := cfg.KeyHeaderValidate(key); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// First-pass: if the idempotency key is in the storage, get and return the response\n\t\tif ok, err := maybeWriteCachedResponse(c, key); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to write cached response at fastpath: %w\", err)\n\t\t} else if ok {\n\t\t\treturn nil\n\t\t}\n\n\t\tif err := cfg.Lock.Lock(key); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to lock: %w\", err)\n\t\t}\n\t\tdefer func() {\n\t\t\tif err := cfg.Lock.Unlock(key); err != nil {\n\t\t\t\tlog.Errorf(\"[IDEMPOTENCY] failed to unlock key %q: %v\", maskKey(key), err)\n\t\t\t}\n\t\t}()\n\n\t\t// Lock acquired. If the idempotency key now is in the storage, get and return the response\n\t\tif ok, err := maybeWriteCachedResponse(c, key); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to write cached response while locked: %w\", err)\n\t\t} else if ok {\n\t\t\treturn nil\n\t\t}\n\n\t\t// Execute the request handler\n\t\tif err := c.Next(); err != nil {\n\t\t\t// If the request handler returned an error, return it and skip idempotency\n\t\t\treturn err","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/middleware/idempotency/idempotency.go#L108-L144","documentation":"Returned when cfg.Lock.Lock(key) fails before executing the request handler. The default in-memory locker does not error, so this only fires with a custom Locker implementation (e.g. a distributed Redis/etcd lock) that fails to acquire the lock — connection error, lock contention timeout, or auth failure.","triggerScenarios":"Providing a custom idempotency.Config.Lock (distributed locker) whose Lock(key) returns a non-nil error. Triggers on locker outage, inability to acquire the lock within the locker's timeout, or a misconfigured locker client.","commonSituations":"Multi-instance deployment using a Redis-based lock where Redis is unreachable, lock TTL too short causing livelock, locker client not initialized, or auth/ACL rejection by the lock backend.","solutions":["Verify the locker backend (Redis/etcd) is reachable and authenticated.","Tune the locker's acquisition timeout/TTL to outlast the slowest handler.","If lock acquisition is best-effort, fall back to per-process memory lock and accept duplicate execution risk.","Ensure exactly one Lock instance is shared across instances (not per-process)."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use a battle-tested distributed locker (Redis redlock, etcd).","Tune lock TTL to outlast the slowest handler.","Have a fallback policy when the lock backend is unavailable."],"tags":["idempotency","distributed-lock","redis","concurrency"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}