gofiber/fiber · warning

csrf: failed to delete token from storage: %w

Error message

csrf: failed to delete token from storage: %w

What it means

Thrown at middleware/csrf/csrf.go:294 by deleteTokenFromStorage() when storageManager.delRaw fails. This path runs for SingleUseToken mode (consuming the token after one unsafe request) and on explicit Handler.DeleteToken. A failed DELETE means the storage backend rejected the operation.

Source

Thrown at middleware/csrf/csrf.go:294

// 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 9a4c7e57fe)

Solutions

  1. Check the wrapped driver error and fix the backend cause (read-only mode, ACLs, capacity, timeout).
  2. Grant the storage user DELETE permission in addition to GET/SET.
  3. Since CSRF tokens are TTL-bounded by IdleTimeout, log delete failures and let the TTL reclaim the token rather than failing the user request.
  4. If SingleUseToken reliability is critical, choose a storage backend with stronger consistency and retry semantics.
  5. Tune the storage write timeout to fit the request deadline.

Example fix

// before: single-use token failure surfaces as 500
app.Use(csrf.New(csrf.Config{
    Storage:        redis.New(),
    SingleUseToken: true,
}))

// after: log + degrade; IdleTimeout reclaims the token anyway
app.Use(csrf.New(csrf.Config{
    Storage:        redis.New(),
    SingleUseToken: true,
    IdleTimeout:    15 * time.Minute,
    ErrorHandler: func(c fiber.Ctx, err error) error {
        if strings.Contains(err.Error(), "failed to delete token") {
            log.Printf("csrf token delete failed (TTL will reclaim): %v", err)
            return c.Next()
        }
        return c.Status(fiber.StatusForbidden).SendString(err.Error())
    },
}))
Defensive patterns

Strategy: fallback

Validate before calling

// At boot, confirm DELETE is permitted (ACLs sometimes omit it).
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
_ = store.SetWithContext(ctx, "__csrf_del_probe__", []byte("+"), time.Minute)
if err := store.DeleteWithContext(ctx, "__csrf_del_probe__"); err != nil {
    log.Fatalf("csrf storage DELETE denied: %v", err)
}

Try / catch

// Best-effort delete: tokens are TTL-bounded by IdleTimeout anyway.
cfg.ErrorHandler = func(c fiber.Ctx, err error) error {
    if strings.Contains(err.Error(), "failed to delete token") {
        log.Printf("csrf delete failed (TTL reclaims): %v", err)
        return c.Next()
    }
    return c.Status(fiber.StatusForbidden).SendString(err.Error())
}

Prevention

When it happens

Trigger: SingleUseToken is enabled and the post-validation DELETE hits a failing Storage backend; or Handler.DeleteToken is called and the storage is down/ACL-restricted/timed out.

Common situations: Storage replica in read-only mode during failover; ACLs that grant SET but not DELETE; backend OOM; ctx cancellation; network blip during the DELETE.

Related errors


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