{"record":{"id":"0c28117d8320ae23","repo":"gofiber/fiber","slug":"errsessionalreadyloadedbymiddleware","errorCode":"ErrSessionAlreadyLoadedByMiddleware","errorMessage":"session already loaded by middleware","messagePattern":"session already loaded by middleware","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"middleware/session/store.go","lineNumber":19,"sourceCode":"package session\n\nimport (\n\t\"context\"\n\t\"encoding/gob\"\n\t\"errors\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/gofiber/fiber/v3\"\n\t\"github.com/gofiber/fiber/v3/extractors\"\n\t\"github.com/gofiber/fiber/v3/internal/storage/memory\"\n\t\"github.com/gofiber/fiber/v3/log\"\n)\n\n// ErrEmptySessionID is an error that occurs when the session ID is empty.\nvar (\n\tErrEmptySessionID                   = errors.New(\"session ID cannot be empty\")\n\tErrSessionAlreadyLoadedByMiddleware = errors.New(\"session already loaded by middleware\")\n\tErrSessionIDNotFoundInStore         = errors.New(\"session ID not found in session store\")\n)\n\n// sessionIDKey is the local key type used to store and retrieve the session ID in context.\ntype sessionIDKey int\n\nconst (\n\t// sessionIDContextKey is the key used to store the session ID in the context locals.\n\tsessionIDContextKey sessionIDKey = iota\n\t// sessionExtractorContextKey stores the extractor that provided the session ID.\n\tsessionExtractorContextKey\n)\n\n// Store manages session data using the configured storage backend.\ntype Store struct {\n\tConfig\n}\n","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/middleware/session/store.go#L1-L37","documentation":"The session middleware loads the session once per request and stores it in context (sessionIDContextKey / sessionExtractorContextKey). Calling Store.Acquire again on the same context would double-load state and cause consistency bugs, so the middleware rejects the second load with ErrSessionAlreadyLoadedByMiddleware.","triggerScenarios":"Manually calling store.Acquire(ctx, id) inside a handler that runs after the session middleware has already loaded the session for that request.","commonSituations":"Applying session middleware to a route AND calling Store methods directly in the handler; calling Acquire twice in nested handlers; helper functions that re-load sessions without checking context.","solutions":["Use ctx.Locals() / the middleware-provided session accessor instead of calling Store.Acquire.","Remove the redundant Store.Acquire call from handlers downstream of session middleware.","If you must manage sessions manually, do not register the session middleware on those routes."],"exampleFix":"// before\napp.Use(session.New())\napp.Get(\"/me\", func(c fiber.Ctx) error {\n    sess, _ := store.Acquire(c.Cookies(\"session\")) // double load\n    return c.JSON(sess)\n})\n\n// after\napp.Use(session.New())\napp.Get(\"/me\", func(c fiber.Ctx) error {\n    sess := localsFromContext(c) // use middleware-loaded session\n    return c.JSON(sess)\n})","handlingStrategy":"validation","validationCode":"// Prefer reading from context instead of double-acquiring\nif v := c.Locals(sessionContextKey); v != nil {\n    sess = v.(*session.Session)\n} else {\n    sess, err = store.Acquire(id)\n}","typeGuard":"func sessionInContext(c fiber.Ctx) (*session.Session, bool) {\n    s, ok := c.Locals(sessionContextKey).(*session.Session)\n    return s, ok\n}","tryCatchPattern":null,"preventionTips":["Don't combine session middleware with manual Store calls on the same route.","Centralize session access behind a helper that checks context first.","Document the one-load-per-request contract for new contributors."],"tags":["session","middleware","api-misuse","context"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}