{"id":"608ab1575fc14dd0","repo":"gofiber/fiber","slug":"limiter-failed-to-unmarshal-key-q-w","errorCode":null,"errorMessage":"limiter: failed to unmarshal key %q: %w","messagePattern":"limiter: failed to unmarshal key %q: %w","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"middleware/limiter/manager.go","lineNumber":76,"sourceCode":"func (m *manager) release(e *item) {\n\te.prevHits = 0\n\te.currHits = 0\n\te.exp = 0\n\tm.pool.Put(e)\n}\n\n// get data from storage or memory\nfunc (m *manager) get(ctx context.Context, key string) (*item, error) {\n\tif m.storage != nil {\n\t\traw, err := m.storage.GetWithContext(ctx, key)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"limiter: failed to get key %q from storage: %w\", m.logKey(key), err)\n\t\t}\n\t\tif raw != nil {\n\t\t\tit := m.acquire()\n\t\t\tif _, err := it.UnmarshalMsg(raw); err != nil {\n\t\t\t\tm.release(it)\n\t\t\t\treturn nil, fmt.Errorf(\"limiter: failed to unmarshal key %q: %w\", m.logKey(key), err)\n\t\t\t}\n\t\t\treturn it, nil\n\t\t}\n\t\treturn m.acquire(), nil\n\t}\n\n\tvalue := m.memory.Get(key)\n\tif value == nil {\n\t\treturn m.acquire(), nil\n\t}\n\n\tit, ok := value.(*item)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"limiter: unexpected entry type %T for key %q\", value, m.logKey(key))\n\t}\n\n\treturn it, nil\n}","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/gofiber/fiber/blob/9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c/middleware/limiter/manager.go#L58-L94","documentation":"Returned by the limiter middleware's storage-backed manager.get when raw bytes retrieved from the external fiber.Storage cannot be deserialized via msgp (UnmarshalMsg) into the internal *item struct (currHits/prevHits/exp). The limiter serializes hit counters with MessagePack, so this error means the bytes under the key are not valid msgp or do not match the item schema.","triggerScenarios":"Limiter is configured with a non-nil fiber.Storage; storage.GetWithContext returns non-nil bytes but it.UnmarshalMsg(raw) fails at manager.go:74. Happens when stored data was written by an incompatible limiter version whose msgp-generated schema differs, when another process wrote arbitrary bytes to the same key, or when the storage backend corrupted the value.","commonSituations":"Upgrading gofiber/fiber across versions where the internal item struct field layout changed; sharing a Redis keyspace between two apps that collide on limiter keys; storage corruption after a Redis crash/restart restore; running two different fiber major versions against the same storage backend.","solutions":["Flush or namespace-isolate the storage keys used by the limiter after upgrading fiber versions (msgp payload is not version-tolerant).","Ensure no other application writes to the limiter's key namespace.","If using Redis, inspect the value under the reported key and confirm it is the expected msgp blob, not corrupt or plaintext.","Pin all instances sharing the storage to a single fiber version."],"exampleFix":"// before: colliding keys across versions\napp.Use(limiter.New(limiter.Config{\n    Storage: redisStore, // default key namespace shared with old version\n}))\n\n// after: isolate keys per deployment version\napp.Use(limiter.New(limiter.Config{\n    Storage: redisStore,\n    KeyGenerator: func(c fiber.Ctx) string {\n        return \"v2:\" + c.IP()\n    },\n}))","handlingStrategy":"validation","validationCode":"// Before wiring the limiter, confirm storage is healthy and isolated.\n// Run once at startup:\nfunc checkLimiterStorage(s fiber.Storage) error {\n    const probe = \"limiter:healthcheck\"\n    if err := s.Set(probe, []byte{0}, time.Second); err != nil {\n        return fmt.Errorf(\"storage unhealthy: %w\", err)\n    }\n    _ = s.Delete(probe)\n    return nil\n}","typeGuard":null,"tryCatchPattern":"// In a fiber error handler, surface limiter storage corruption as a 503\n// rather than a generic 500, so clients retry.\napp := fiber.New(fiber.Config{\n    ErrorHandler: func(c fiber.Ctx, err error) error {\n        var msg string = err.Error()\n        if strings.Contains(msg, \"limiter: failed to unmarshal key\") {\n            return c.Status(fiber.StatusServiceUnavailable).SendString(\"rate store unavailable\")\n        }\n        return c.Status(fiber.StatusInternalServerError).SendString(err.Error())\n    },\n})","preventionTips":["Namespace limiter keys per deployment/version when sharing storage.","Flush limiter keys when upgrading fiber major versions.","Never share the limiter's storage keyspace with other apps.","Monitor storage backend health and connectivity."],"tags":["limiter","storage","msgp","serialization","deserialization","version-mismatch"],"analyzedSha":"9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c","analyzedAt":"2026-08-04T21:44:03.395Z","schemaVersion":2}