{"record":{"id":"51ef8f6d8654fa3e","repo":"crowdsecurity/crowdsec","slug":"w-s","errorCode":null,"errorMessage":"%w: %s","messagePattern":"%w: %s","errorType":"exception","errorClass":"ErrTokenParse","httpStatus":null,"severity":"error","filePath":"pkg/database/token.go","lineNumber":43,"sourceCode":"}\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\n\texpFloat, ok := claims[\"exp\"].(float64)\n\tif !ok {\n\t\treturn APICToken{}, fmt.Errorf(\"%w: exp\", ErrTokenMissingClaim)\n\t}\n\n\texp := time.Unix(int64(expFloat), 0)\n\tif time.Now().UTC().After(exp.Add(-1 * time.Minute)) {\n\t\treturn APICToken{}, ErrTokenExpired\n\t}\n\n\treturn APICToken{Raw: token, ExpiresAt: exp}, nil","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/database/token.go#L25-L61","documentation":"LoadAPICToken calls ParseUnverified to decode the stored CAPI JWT. If the token string cannot be parsed as a JWT (malformed, truncated, not a token at all), the returned error wraps ErrTokenParse with the parser message. This is a data problem in the stored token, not a network or DB connectivity problem.","triggerScenarios":"Calling LoadAPICToken when the config item contains a corrupt or hand-edited token string; a failed/partial SaveAPICToken wrote garbage; an old token format incompatible with the current parser.","commonSituations":"Manual editing of the DB/config by an operator; restore from an inconsistent backup; upgrade across versions where token generation changed.","solutions":["Delete/re-register the token: 'cscli capi delete' then 'cscli capi register', or clear the APICTokenKey config item and re-authenticate to store a fresh JWT.","Verify the stored value actually looks like a JWT (three dot-separated base64url segments).","Never hand-edit the token in the database; use cscli commands."],"exampleFix":"// caller: treat parse failure as 'token unusable', force re-auth\ntok, err := c.LoadAPICToken(ctx, log)\nif errors.Is(err, database.ErrTokenParse) {\n    log.Warn(\"stored CAPI token corrupt, re-authenticating\")\n    return authenticate(ctx)\n}","handlingStrategy":"try-catch","validationCode":"// quick structural sanity check on a stored token string before parsing\nfunc looksLikeJWT(tok string) bool {\n    parts := strings.Split(tok, \".\")\n    return len(parts) == 3 && parts[0] != \"\" && parts[1] != \"\"\n}","typeGuard":"func isTokenParseErr(err error) bool { return errors.Is(err, database.ErrTokenParse) }","tryCatchPattern":"tok, err := client.LoadAPICToken(ctx, log)\nif isTokenParseErr(err) {\n    log.Warn(\"stored CAPI token is corrupt, forcing re-authentication\")\n    return reauthenticate(ctx)\n}","preventionTips":["Never hand-edit or paste tokens into the database.","Restore DB and config items together from consistent backups.","Use cscli capi register/login for all token lifecycle changes.","Validate a restored token's shape before relying on it."],"tags":["jwt","token","parse-error","capi"],"backgroundTag":"jwt-parse-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"}