gofiber/fiber · error · ErrTokenNotFound

csrf: token not found

Error message

csrf: token not found

What it means

Returned by the CSRF middleware (csrf.go:23) when an unsafe HTTP method (POST, PUT, PATCH, DELETE, etc.) is received and the configured Extractor cannot find a CSRF token, or finds an empty string, or the token is not present in server-side storage (expired or never created). The middleware uses double-submit-cookie plus server-side storage validation, so the token must exist in the request payload/header AND in storage. Triggered from csrf.go:168, 175, 195, and 332.

Source

Thrown at middleware/csrf/csrf.go:23

	"fmt"
	"net/url"
	"slices"
	"strings"
	"sync"
	"time"

	"github.com/gofiber/utils/v2"
	utilsstrings "github.com/gofiber/utils/v2/strings"

	"github.com/gofiber/fiber/v3"
	"github.com/gofiber/fiber/v3/extractors"
	"github.com/gofiber/fiber/v3/internal/redact"
	"github.com/gofiber/fiber/v3/internal/schemehost"
	"github.com/gofiber/fiber/v3/middleware/logger"
)

var (
	ErrTokenNotFound    = errors.New("csrf: token not found")
	ErrTokenInvalid     = errors.New("csrf: token invalid")
	ErrFetchSiteInvalid = errors.New("csrf: sec-fetch-site header invalid")
	ErrRefererNotFound  = errors.New("csrf: referer header missing")
	ErrRefererInvalid   = errors.New("csrf: referer header invalid")
	ErrRefererNoMatch   = errors.New("csrf: referer does not match host or trusted origins")
	ErrOriginInvalid    = errors.New("csrf: origin header invalid")
	ErrOriginNoMatch    = errors.New("csrf: origin does not match host or trusted origins")
	errOriginNotFound   = errors.New("origin not supplied or is null") // internal error, will not be returned to the user
	dummyValue          = []byte{'+'}                                  // dummyValue is a placeholder value stored in token storage. The actual token validation relies on the key, not this value.

)

var registerLogContextTagsOnce sync.Once

// Handler for CSRF middleware
type Handler struct {
	sessionManager *sessionManager
	storageManager *storageManager

View on GitHub (pinned to 9a4c7e57fe)

Solutions

  1. Ensure the frontend reads the CSRF token from the cookie/endpoint and sends it on every unsafe-method request via the configured header or form field.
  2. If running multiple instances, configure a shared Storage (Redis, etc.) instead of the default in-memory storage so tokens are valid cluster-wide.
  3. Increase IdleTimeout / Expiration if tokens expire too quickly for your users.
  4. If SingleUseToken is enabled, ensure the client fetches a fresh token after each mutating request.

Example fix

// before — fetch POST with no CSRF header
fetch('/api/update', {method:'POST', credentials:'same-origin', body:data})
// after — read token from cookie and send as header
function getCookie(n){return document.cookie.match(n+'=([^;]+)')?.[1]}
fetch('/api/update', {method:'POST', credentials:'same-origin',
  headers:{'X-Csrf-Token': getCookie('csrf_')}, body:data})
Defensive patterns

Strategy: validation

Validate before calling

// Frontend: ensure token is attached before sending unsafe requests
function safeFetch(url, opts={}) {
  if (['POST','PUT','PATCH','DELETE'].includes(opts.method)) {
    opts.headers = opts.headers || {}
    opts.headers['X-Csrf-Token'] = getCookie('csrf_')
  }
  return fetch(url, {credentials:'same-origin', ...opts})
}

Try / catch

// Customize the CSRF error handler to guide clients
app.Use(csrf.New(csrf.Config{
  ErrorHandler: func(c fiber.Ctx, err error) error {
    if errors.Is(err, csrf.ErrTokenNotFound) {
      return c.Status(403).JSON(fiber.Map{"error":"CSRF token missing or expired. Fetch a new token."})
    }
    return c.Status(403).SendString(err.Error())
  },
}))

Prevention

When it happens

Trigger: A state-changing request (POST/PUT/PATCH/DELETE) is sent without the CSRF token in the location the Extractor is configured to read (default: form field '_csrf' or header 'X-Csrf-Token'); or the token cookie expired; or the token was already consumed (SingleUseToken=true); or the client sent a token that was never issued by this server instance (e.g. after a restart with in-memory storage).

Common situations: Frontend SPA forgot to include the CSRF token header on a fetch POST; cookie was cleared; load-balanced deployment with in-memory storage where the token was issued by a different instance; token expired due to IdleTimeout; using SingleUseToken and the client retried a request.

Related errors


AI-assisted analysis of gofiber/fiber@9a4c7e57fe (2026-08-04). Data as JSON: /data/errors/7785a79e7c20f8de.json. Report an issue: GitHub.