{"record":{"id":"e2a3fcc27de3f142","repo":"crowdsecurity/crowdsec","slug":"loading-token-w","errorCode":null,"errorMessage":"loading token: %w","messagePattern":"loading token: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/database/token.go","lineNumber":32,"sourceCode":"\nvar (\n\tErrTokenNotFound     = errors.New(\"token not found in DB\")\n\tErrTokenParse        = errors.New(\"unable to parse token\")\n\tErrTokenMissingClaim = errors.New(\"token missing required claim\")\n\tErrTokenExpired      = errors.New(\"token expired\")\n)\n\ntype APICToken struct {\n\tRaw       string\n\tExpiresAt time.Time\n}\n\n// LoadAPICToken attempts to retrieve and validate a JWT token from the local database.\n// Errors are returned if the token can't be read, is not valid, expired or has no expiration.\nfunc (c *Client) LoadAPICToken(ctx context.Context, logger logrus.FieldLogger) (APICToken, error) {\n\ttoken, err := c.GetConfigItem(ctx, APICTokenKey) // TokenKey is a constant string representing the key for the token in the database\n\tif err != nil {\n\t\treturn APICToken{}, fmt.Errorf(\"loading token: %w\", err)\n\t}\n\n\tif token == \"\" {\n\t\treturn APICToken{}, ErrTokenNotFound\n\t}\n\n\tparser := new(jwt.Parser)\n\n\ttok, _, err := parser.ParseUnverified(token, jwt.MapClaims{})\n\tif err != nil {\n\t\treturn APICToken{}, fmt.Errorf(\"%w: %s\", ErrTokenParse, err)\n\t}\n\n\tclaims, ok := tok.Claims.(jwt.MapClaims)\n\tif !ok {\n\t\treturn APICToken{}, ErrTokenParse\n\t}\n","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/database/token.go#L14-L50","documentation":"LoadAPICToken reads the stored CAPI JWT from the config-items table via GetConfigItem. If that read fails (database-level error, not an empty token), this wrapped error is returned. A missing/empty token returns ErrTokenNotFound instead, and later steps can return ErrTokenParse/ErrTokenExpired.","triggerScenarios":"Calling LoadAPICToken (from Authenticate) when GetConfigItem fails: unreadable or locked SQLite DB, corrupted config-items table, disk I/O error, canceled context.","commonSituations":"Permissions changed on crowdsec.db during backup/restore; SQLite locked by a long-running cscli command; DB corruption after disk failure.","solutions":["Check logs for the underlying GetConfigItem error (the %w chain contains the raw DB error).","Fix DB file permissions/ownership for the crowdsec process.","If the DB is corrupt, restore it or re-register ('cscli capi register') which re-creates the token via SaveAPICToken.","If it turns out the token is merely absent/invalid, re-authenticate: 'cscli capi register' + login to get a fresh JWT."],"exampleFix":"// caller: distinguish DB failure from token problems\ntok, err := c.LoadAPICToken(ctx, log)\nswitch {\ncase errors.Is(err, database.ErrTokenNotFound), errors.Is(err, database.ErrTokenExpired):\n    // re-authenticate, normal path\n    return authenticate(ctx)\ncase err != nil:\n    return fmt.Errorf(\"token storage unreadable: %w\", err) // real DB problem\n}","handlingStrategy":"try-catch","validationCode":"// before loading, confirm the DB is reachable\nctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\ndefer cancel()","typeGuard":null,"tryCatchPattern":"tok, err := client.LoadAPICToken(ctx, log)\nswitch {\ncase errors.Is(err, database.ErrTokenNotFound),\n     errors.Is(err, database.ErrTokenParse),\n     errors.Is(err, database.ErrTokenExpired),\n     errors.Is(err, database.ErrTokenMissingClaim):\n    return reauthenticate(ctx) // expected paths: get a fresh token\ncase err != nil:\n    return fmt.Errorf(\"token storage unreadable: %w\", err) // DB-level problem\n}","preventionTips":["Use errors.Is against the ErrToken* sentinels to branch correctly.","Never edit the token in the DB manually — use cscli capi register.","Keep DB file permissions correct for the crowdsec service user.","Verify DB integrity after disk events."],"tags":["database","sqlite","token","capi"],"backgroundTag":"file-read-failed","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}