{"record":{"id":"eebfeac758d15168","repo":"gofiber/fiber","slug":"invalid-idempotency-key","errorCode":null,"errorMessage":"invalid idempotency key","messagePattern":"invalid idempotency key","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"middleware/idempotency/config.go","lineNumber":12,"sourceCode":"package idempotency\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/gofiber/fiber/v3\"\n\t\"github.com/gofiber/fiber/v3/internal/storage/memory\"\n)\n\nvar ErrInvalidIdempotencyKey = errors.New(\"invalid idempotency key\")\n\n// Config defines the config for middleware.\ntype Config struct {\n\t// Lock locks an idempotency key.\n\t//\n\t// Optional. Default: an in-memory locker for this process only.\n\tLock Locker\n\n\t// Storage stores response data by idempotency key.\n\t//\n\t// Optional. Default: an in-memory storage for this process only.\n\tStorage fiber.Storage\n\n\t// Next defines a function to skip this middleware when returned true.\n\t//\n\t// Optional. Default: a function which skips the middleware on safe HTTP request method.\n\tNext func(c fiber.Ctx) bool\n","sourceCodeStart":1,"sourceCodeEnd":30,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/middleware/idempotency/config.go#L1-L30","documentation":"Returned by middleware/idempotency when the idempotency key header fails validation. The default Config.KeyHeaderValidate requires the key to be exactly 36 characters (UUID length), and the middleware wraps the failure as fmt.Errorf(\"%w: invalid length: %d != %d\", ErrInvalidIdempotencyKey, ...). It is the package sentinel that errors.Is matches against.","triggerScenarios":"A non-safe request carrying an X-Idempotency-Key header (default name) whose value is not 36 characters, with the default validator. Safe methods (GET/HEAD/etc.) are skipped by the default Next, so this only fires on POST/PUT/DELETE/PATCH.","commonSituations":"Client sends a non-UUID key (sequential id, timestamp, truncated UUID); custom KeyHeaderValidate is set but the client violates its rule; header name mismatch so an empty/garbage value is read.","solutions":["Send a valid 36-character UUID in the X-Idempotency-Key header on mutations.","If your key format differs, set Config.KeyHeaderValidate to a function that accepts your format.","Make sure Config.KeyHeader matches the header name your client actually sends.","Generate keys client-side with a UUID library and reuse the same key for retries of the same logical request."],"exampleFix":"// before: arbitrary key\nreq.Header.Set(\"X-Idempotency-Key\", \"order-12345\")\n// after: UUID\nreq.Header.Set(\"X-Idempotency-Key\", \"550e8400-e29b-41d4-a716-446655440000\")\n// or relax the validator\nidempotency.New(idempotency.Config{\n  KeyHeaderValidate: func(k string) error { return nil },\n})","handlingStrategy":"validation","validationCode":"func validUUID(s string) error {\n    if len(s) != 36 { return idempotency.ErrInvalidIdempotencyKey }\n    if _, err := uuid.Parse(s); err != nil { return err }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if err := validate(key); err != nil {\n    if errors.Is(err, idempotency.ErrInvalidIdempotencyKey) {\n        // client must resend with a 36-char UUID; do not retry the same key\n    }\n}","preventionTips":["Generate idempotency keys with a UUID library and reuse them only for retries.","Set KeyHeader to match the header your client sends.","If non-UUID keys are needed, replace KeyHeaderValidate with a matching rule."],"tags":["idempotency","config","headers"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}