crowdsecurity/crowdsec · error
loading token: %w
Error message
loading token: %w
What it means
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.
Source
Thrown at pkg/database/token.go:32
var (
ErrTokenNotFound = errors.New("token not found in DB")
ErrTokenParse = errors.New("unable to parse token")
ErrTokenMissingClaim = errors.New("token missing required claim")
ErrTokenExpired = errors.New("token expired")
)
type APICToken struct {
Raw string
ExpiresAt time.Time
}
// LoadAPICToken attempts to retrieve and validate a JWT token from the local database.
// Errors are returned if the token can't be read, is not valid, expired or has no expiration.
func (c *Client) LoadAPICToken(ctx context.Context, logger logrus.FieldLogger) (APICToken, error) {
token, err := c.GetConfigItem(ctx, APICTokenKey) // TokenKey is a constant string representing the key for the token in the database
if err != nil {
return APICToken{}, fmt.Errorf("loading token: %w", err)
}
if token == "" {
return APICToken{}, ErrTokenNotFound
}
parser := new(jwt.Parser)
tok, _, err := parser.ParseUnverified(token, jwt.MapClaims{})
if err != nil {
return APICToken{}, fmt.Errorf("%w: %s", ErrTokenParse, err)
}
claims, ok := tok.Claims.(jwt.MapClaims)
if !ok {
return APICToken{}, ErrTokenParse
}
View on GitHub (pinned to 909b515798)
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.
Example fix
// caller: distinguish DB failure from token problems
tok, err := c.LoadAPICToken(ctx, log)
switch {
case errors.Is(err, database.ErrTokenNotFound), errors.Is(err, database.ErrTokenExpired):
// re-authenticate, normal path
return authenticate(ctx)
case err != nil:
return fmt.Errorf("token storage unreadable: %w", err) // real DB problem
} Defensive patterns
Strategy: try-catch
Validate before calling
// before loading, confirm the DB is reachable ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel()
Try / catch
tok, err := client.LoadAPICToken(ctx, log)
switch {
case errors.Is(err, database.ErrTokenNotFound),
errors.Is(err, database.ErrTokenParse),
errors.Is(err, database.ErrTokenExpired),
errors.Is(err, database.ErrTokenMissingClaim):
return reauthenticate(ctx) // expected paths: get a fresh token
case err != nil:
return fmt.Errorf("token storage unreadable: %w", err) // DB-level problem
} Prevention
- 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.
When it happens
Trigger: Calling LoadAPICToken (from Authenticate) when GetConfigItem fails: unreadable or locked SQLite DB, corrupted config-items table, disk I/O error, canceled context.
Common situations: Permissions changed on crowdsec.db during backup/restore; SQLite locked by a long-running cscli command; DB corruption after disk failure.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- saving token: %w
- while saving alert from %s: %w
- token not found in DB
- while getting allowlist %s: %s
- while creating allowlist %s: %s
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/e2a3fcc27de3f142.
Report an issue: GitHub.