crowdsecurity/crowdsec · error

token missing required claim

Error message

token missing required claim

What it means

After parsing the CAPI JWT, LoadAPICToken requires the standard 'exp' claim as a numeric (float64) value. ErrTokenMissingClaim is returned (wrapped with the claim name, e.g. 'exp') when the claim is absent or not a number, meaning expiry cannot be evaluated.

Source

Thrown at pkg/database/token.go:18

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. Re-enroll with CAPI to obtain a fresh standards-compliant JWT
  2. Verify the token contains a numeric exp claim (decode with jwt.io or jwt-ish tooling)
  3. Delete the bad token row and let the puller fetch a new one

Example fix

if errors.Is(err, dbclient.ErrTokenMissingClaim) {
    // token lacks exp: force refresh via re-enrollment
    _ = client.DeleteAPICToken(ctx)
}
Defensive patterns

Strategy: try-catch

Try / catch

if errors.Is(err, dbclient.ErrTokenMissingClaim) {
    // unusable token: clear and force re-fetch/enrollment
    _ = client.DeleteAPICToken(ctx)
    return refreshCAPIToken(ctx)
}

Prevention

When it happens

Trigger: The stored token's claims map lacks 'exp', or exp is a string/other JSON type instead of a number (token.go:53).

Common situations: Custom/hand-crafted JWT stored in the DB, upstream token format change, corrupted token where only some claims survive.

Related errors


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