gofiber/fiber · error

csrf: failed to fetch token from storage: %w

Error message

csrf: failed to fetch token from storage: %w

What it means

Thrown at middleware/csrf/csrf.go:271 by getRawFromStorage() when storageManager.getRaw returns a non-nil error during token validation lookup. The CSRF middleware is trying to confirm the submitted token exists in storage and the Storage backend GET failed. The wrapped %w is the inner 'csrf: failed to get value from storage' error (153), which itself wraps the raw driver error.

Source

Thrown at middleware/csrf/csrf.go:271

// It accepts fiber.CustomCtx, fiber.Ctx, *fasthttp.RequestCtx, and context.Context.
// It returns nil if the handler does not exist.
func HandlerFromContext(ctx any) *Handler {
	if handler, ok := fiber.ValueFromContext[*Handler](ctx, handlerKey); ok {
		return handler
	}

	return nil
}

// getRawFromStorage returns the raw value from the storage for the given token
// returns nil if the token does not exist, is expired or is invalid
func getRawFromStorage(c fiber.Ctx, token string, cfg *Config, sessionManager *sessionManager, storageManager *storageManager) ([]byte, error) {
	if cfg.Session != nil {
		return sessionManager.getRaw(c, token, dummyValue), nil
	}
	raw, err := storageManager.getRaw(c, token)
	if err != nil {
		return nil, fmt.Errorf("csrf: failed to fetch token from storage: %w", err)
	}
	return raw, nil
}

// createOrExtendTokenInStorage creates or extends the token in the storage
func createOrExtendTokenInStorage(c fiber.Ctx, token string, cfg *Config, sessionManager *sessionManager, storageManager *storageManager) error {
	if cfg.Session != nil {
		sessionManager.setRaw(c, token, dummyValue, cfg.IdleTimeout)
		return nil
	}
	if err := storageManager.setRaw(c, token, dummyValue, cfg.IdleTimeout); err != nil {
		return fmt.Errorf("csrf: failed to store token in storage: %w", err)
	}
	return nil
}

func deleteTokenFromStorage(c fiber.Ctx, token string, cfg *Config, sessionManager *sessionManager, storageManager *storageManager) error {
	if cfg.Session != nil {

View on GitHub (pinned to 9a4c7e57fe)

Solutions

  1. Inspect the wrapped error chain down to the driver error and fix the underlying backend issue (connectivity, auth, timeout).
  2. Point cfg.Storage at a healthy backend and confirm connectivity at boot with a probe GET.
  3. Tune the storage read timeout to fit within the request deadline.
  4. Provide a custom cfg.ErrorHandler that returns a clear 5xx with retry guidance rather than leaking the storage error to the client.
  5. Consider cfg.Session integration if you already run a session store, so CSRF reuses its (presumably healthy) backend.

Example fix

// before
csrfStorage := redis.New()
app.Use(csrf.New(csrf.Config{ Storage: csrfStorage }))

// after: boot-time probe + clear error handler
if _, err := csrfStorage.Get("__probe__"); err != nil {
    log.Fatalf("csrf storage unhealthy at boot: %v", err)
}
app.Use(csrf.New(csrf.Config{
    Storage: csrfStorage,
    ErrorHandler: func(c fiber.Ctx, err error) error {
        if strings.Contains(err.Error(), "failed to fetch token from storage") {
            return c.Status(fiber.StatusServiceUnavailable).
                SendString("session store temporarily unavailable; please retry")
        }
        return c.Status(fiber.StatusForbidden).SendString(err.Error())
    },
}))
Defensive patterns

Strategy: try-catch

Validate before calling

// At boot, confirm the CSRF storage backend is reachable.
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
if _, err := store.GetWithContext(ctx, "__csrf_probe__"); err != nil {
    log.Fatalf("csrf storage unhealthy: %v", err)
}

Try / catch

// Provide a CSRF ErrorHandler that degrades clearly on storage failures.
cfg.ErrorHandler = func(c fiber.Ctx, err error) error {
    if strings.Contains(err.Error(), "failed to fetch token from storage") {
        c.Set(fiber.HeaderRetryAfter, "5")
        return c.Status(fiber.StatusServiceUnavailable).
            SendString("token store unavailable; retry shortly")
    }
    return c.Status(fiber.StatusForbidden).SendString(err.Error())
}

Prevention

When it happens

Trigger: A state-changing request (POST/PUT/DELETE/...) reaches the CSRF middleware with a token, and storageManager.getRaw -> Storage.GetWithContext errors out: backend down, timeout, ctx cancelled, or auth failure.

Common situations: Session/CSRF Redis down during a deploy; storage credentials rotated but app not restarted; client disconnect mid-request; network partition to the session store.

Related errors


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