gofiber/fiber · warning

csrf: failed to delete token from storage

Error message

csrf: failed to delete token from storage: %w

What it means

Returned by deleteTokenFromStorage when storageManager.delRaw fails during CSRF token invalidation (logout, double-submit cleanup, token rotation). The token remains in storage and could still validate a request until it expires via TTL.

Solutions

  1. Inspect the wrapped error for permission/connectivity/cancellation.
  2. Ensure Storage credentials include DEL permission.
  3. Keep IdleTimeout (TTL) short enough that a failed delete self-heals quickly.
  4. Log the failure; do not block the user-facing logout flow on it — the TTL is the safety net.

Example fix

// before: failing logout because the token delete errored
if err := storageManager.delRaw(c, token); err != nil {
    return fmt.Errorf("csrf: failed to delete token from storage: %w", err)
}

// after: best-effort delete, TTL is the backstop
if err := storageManager.delRaw(c, token); err != nil {
    log.Warn("csrf token delete failed; will expire via TTL:", err)
}
Defensive patterns

Strategy: fallback

Validate before calling

func validateCsrfDelete(ctx context.Context, s fiber.Storage) error {
    _ = s.SetWithContext(ctx, "__csrf_del__", []byte("x"), time.Second)
    return s.DeleteWithContext(ctx, "__csrf_del__")
}

Try / catch

// Logout/invalidation should not fail because the delete errored.
if err := storageManager.delRaw(c, token); err != nil {
    log.Warn("csrf token delete failed; TTL will expire it:", err)
}
return nil

Prevention

When it happens

Trigger: Token invalidation flow (logout, failed-validation purge, single-use token consumption) where the Storage DeleteWithContext errors. Only on the external-Storage branch (cfg.Session nil).

Common situations: Storage outage during logout; ACL missing DEL permission; connection error; context cancellation; backend failover mid-delete. The token will linger until its TTL elapses, slightly widening its validity window.

Related errors


AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11). Data as JSON: /api/errors/3d17d41087a22d6f. Report an issue: GitHub.

Appendix: source

Thrown at middleware/csrf/csrf.go:297

// 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 {
		sessionManager.delRaw(c)
		return nil
	}
	if err := storageManager.delRaw(c, token); err != nil {
		return fmt.Errorf("csrf: failed to delete token from storage: %w", err)
	}
	return nil
}

// Update CSRF cookie
// if expireCookie is true, the cookie will expire immediately
func updateCSRFCookie(c fiber.Ctx, cfg *Config, token string) {
	setCSRFCookie(c, cfg, token, cfg.IdleTimeout)
}

func expireCSRFCookie(c fiber.Ctx, cfg *Config) {
	setCSRFCookie(c, cfg, "", -time.Hour)
}

func setCSRFCookie(c fiber.Ctx, cfg *Config, token string, expiry time.Duration) {
	cookie := &fiber.Cookie{
		Name:        cfg.CookieName,
		Value:       token,

View on GitHub (pinned to a105acad6c)