crowdsecurity/crowdsec · info

token expired

Error message

token expired

What it means

LoadAPICToken rejects tokens that expire within 1 minute of now (time.Now().UTC().After(exp - 1m)), returning the ErrTokenExpired sentinel so callers can distinguish 'needs refresh' from hard failures. This lets the CAPI puller fetch a fresh token rather than pull blocklists with a dying token.

Source

Thrown at pkg/database/token.go:19

package database

import (
	"context"
	"errors"
	"fmt"
	"time"

	"github.com/golang-jwt/jwt/v4"
	"github.com/sirupsen/logrus"
)

const APICTokenKey = "apic_token"

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
	}

View on GitHub (pinned to 909b515798)

Solutions

  1. Let the caller refresh the token from CAPI (the puller does this automatically when errors.Is(err, ErrTokenExpired))
  2. Check host clock sync (NTP) if tokens expire prematurely
  3. Enrollment key invalid? Re-enroll with cscli capi enroll if refresh keeps failing

Example fix

tok, err := client.LoadAPICToken(ctx)
if errors.Is(err, dbclient.ErrTokenExpired) {
    tok, err = refreshCAPIToken(ctx)
}
Defensive patterns

Strategy: retry

Try / catch

tok, err := client.LoadAPICToken(ctx)
if errors.Is(err, dbclient.ErrTokenExpired) {
    tok, err = fetchFreshCAPIToken(ctx) // retry with new token
}
if err != nil {
    return err
}

Prevention

When it happens

Trigger: Calling LoadAPICToken when the stored token's exp claim is in the past, or within 60 seconds of the current UTC time.

Common situations: crowdsec offline longer than the token validity window (tokens typically last ~1h), clock skew on the host, long-lived process that never refreshed its token.

Understand the failure class

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/43a8973280d67bb9. Report an issue: GitHub.