{"record":{"id":"3e574ca89b922ad4","repo":"kataras/iris","slug":"key-not-found","errorCode":null,"errorMessage":"key not found","messagePattern":"key not found","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"info","filePath":"sessions/sessiondb/redis/database.go","lineNumber":316,"sourceCode":"// Close terminates the redis connection.\nfunc (db *Database) Close() error {\n\treturn closeDB(db)\n}\n\nfunc closeDB(db *Database) error {\n\treturn db.c.Driver.CloseConnection()\n}\n\nvar (\n\t// ErrRedisClosed an error with message 'redis: already closed'\n\tErrRedisClosed = errors.New(\"redis: already closed\")\n\t// ErrKeyNotFound a type of error of non-existing redis keys.\n\t// The producers(the library) of this error will dynamically wrap this error(fmt.Errorf) with the key name.\n\t// Usage:\n\t// if err != nil && errors.Is(err, ErrKeyNotFound) {\n\t// [...]\n\t// }\n\tErrKeyNotFound = errors.New(\"key not found\")\n)\n","sourceCodeStart":298,"sourceCodeEnd":318,"githubUrl":"https://github.com/kataras/iris/blob/7bedaf55a0b64bbb2248a5845a2c60d81a30996a/sessions/sessiondb/redis/database.go#L298-L318","documentation":"ErrKeyNotFound ('key not found') signals that a redis key for a session ID does not exist. Producers wrap it with fmt.Errorf to include the missing key name, so callers must check with errors.Is rather than string equality. It lets the session manager treat a missing session as an expired/invalid session instead of a hard failure.","triggerScenarios":"Database.Acquire called with a session ID that no longer exists in redis (expired TTL, flushed DB, or never-created ID); Decode called with data/key absent from the store.","commonSituations":"Users returning after redis TTL expiry or a redis restart (no persistence); a load balancer routing to a different instance whose redis lacks the session; clients replaying stale session cookies after a cache flush.","solutions":["Treat it as 'session expired': regenerate a new session and re-authenticate the user","Check errors.Is(err, redisdb.ErrKeyNotFound) before generic error handling so expiry is not logged as a failure","Enable redis persistence (AOF/RDB) or sticky sessions if losing sessions across restarts is unacceptable"],"exampleFix":"// before\nif err := db.Acquire(sid); err != nil { return err }\n// after\nif err := db.Acquire(sid); err != nil {\n    if errors.Is(err, redisdb.ErrKeyNotFound) {\n        sid, _ = db.Acquire(\"\") // new session\n    } else { return err }\n}","handlingStrategy":"type-guard","validationCode":"// cannot pre-check remote existence cheaply; optionally:\nexists, _ := store.Exists(sid)\nif !exists { sid = \"\" } // force new session","typeGuard":"func isKeyNotFound(err error) bool { return errors.Is(err, redisdb.ErrKeyNotFound) }","tryCatchPattern":"if err := db.Acquire(sid); err != nil {\n    if errors.Is(err, redisdb.ErrKeyNotFound) {\n        sid, err = db.Acquire(\"\") // regenerate session\n    }\n    return sid, err\n}","preventionTips":["Always branch with errors.Is(err, ErrKeyNotFound) — the message includes the key name so string matching breaks","Design expiry as a normal flow: recreate sessions on miss","Enable redis persistence or use session replication to reduce misses"],"tags":["redis","sessions","key-not-found"],"backgroundTag":"cache-miss-key-not-found","analyzedSha":"7bedaf55a0b64bbb2248a5845a2c60d81a30996a","analyzedAt":"2026-08-30T20:38:16.250Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}