{"record":{"id":"8e80757be9623ce4","repo":"crowdsecurity/crowdsec","slug":"unable-to-parse-token","errorCode":null,"errorMessage":"unable to parse token","messagePattern":"unable to parse token","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/database/token.go","lineNumber":17,"sourceCode":"package database\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/golang-jwt/jwt/v4\"\n\t\"github.com/sirupsen/logrus\"\n)\n\nconst APICTokenKey = \"apic_token\"\n\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 == \"\" {","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/database/token.go#L1-L35","documentation":"LoadAPICToken parses the stored JWT without signature verification (ParseUnverified) to read claims. ErrTokenParse is returned when the raw string is not parseable as a JWT, or when the parsed token's claims don't hold jwt.MapClaims. It is always wrapped with the underlying parse error when available.","triggerScenarios":"The apic_token row in the DB contains a malformed/non-JWT string; claims type assertion to jwt.MapClaims fails (token.go:48).","commonSituations":"Manual DB edits corrupting the token, a proxy/placeholder value stored instead of a real JWT, version mismatch writing a different token format.","solutions":["Re-enroll with CAPI (cscli capi enroll) to overwrite the stored token with a fresh valid JWT","Delete the corrupted apic_token row so a new one can be fetched","Inspect the stored value; only a real three-part JWT is accepted"],"exampleFix":"if errors.Is(err, dbclient.ErrTokenParse) {\n    // token corrupt: clear and re-enroll\n    _ = client.DeleteAPICToken(ctx)\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if errors.Is(err, dbclient.ErrTokenParse) {\n    // token corrupt: delete and re-enroll/refresh\n    _ = client.DeleteAPICToken(ctx)\n    return refreshCAPIToken(ctx)\n}","preventionTips":["Never hand-edit the apic_token DB value","Re-enroll to replace corrupted tokens","Log the wrapped cause (fmt.Errorf %w chain) before recovery"],"tags":["jwt","parsing","capi","crowdsec"],"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"}