gofiber/fiber · error

limiter: failed to store key

Error message

limiter: failed to store key %q: %w

What it means

The companion write error to error 180: storage.SetWithContext failed when persisting the updated hit count and expiry. The *item is released back to the pool on failure. The wrapped storage error is preserved for diagnosis.

Solutions

  1. Unwrap the error to find the storage-specific cause (e.g. OOM, LOCK_WAIT_TIMEOUT).
  2. For Redis: raise maxmemory or switch to an eviction policy that suits limiter semantics (allkeys-lru), and confirm maxclients is above your peak concurrency.
  3. Confirm the storage connection pool size >= expected concurrent limiter writes.
  4. Shorten limiter Expiration to reduce storage churn if keys accumulate.
  5. If context cancellation is the cause, ensure the request lifetime exceeds storage write latency.

Example fix

// before: default redis with noeviction, writes fail under load
redis.NewRaw(redis.Config{URL: redisURL})

// after: sized maxmemory and eviction
redis.NewRaw(redis.Config{URL: redisURL}) // plus redis.conf: maxmemory 256mb, maxmemory-policy allkeys-lru
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight: confirm storage write capacity.
if err := store.Set("healthcheck", []byte("ok"), time.Minute); err != nil {
  return fmt.Errorf("storage not writable: %w", err)
}

Try / catch

// On write failure, degrade gracefully (e.g. fail-open with a log) if business permits.
if errors.Is(err, storage.ErrWrite) {
  log.Printf("limiter write failed, failing open: %v", err)
}

Prevention

When it happens

Trigger: Redis OOM (maxmemory exceeded with noeviction), MySQL deadlocks or lock-wait timeout, storage disk full (SQLite), connection pool exhausted, context cancelled mid-write, ACL/permission denied on the storage namespace.

Common situations: Rate-limiter writes are write-heavy (one Set per request that hits the limiter); a Redis maxmemory policy of noeviction will start rejecting writes once the limit is hit; storage backend restarted mid-request; network partition between app and storage.

Related errors


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

Appendix: source

Thrown at middleware/limiter/manager.go:106

	it, ok := value.(*item)
	if !ok {
		return nil, fmt.Errorf("limiter: unexpected entry type %T for key %q", value, m.logKey(key))
	}

	return it, nil
}

// set data to storage or memory
func (m *manager) set(ctx context.Context, key string, it *item, exp time.Duration) error {
	if m.storage != nil {
		raw, err := it.MarshalMsg(nil)
		if err != nil {
			m.release(it)
			return fmt.Errorf("limiter: failed to marshal key %q: %w", m.logKey(key), err)
		}
		if err := m.storage.SetWithContext(ctx, key, raw, exp); err != nil {
			m.release(it)
			return fmt.Errorf("limiter: failed to store key %q: %w", m.logKey(key), err)
		}
		m.release(it)
		return nil
	}

	m.memory.Set(key, it, exp)
	return nil
}

func (m *manager) logKey(key string) string {
	if m.shouldRedactKeys {
		return redactedKey
	}
	return key
}

View on GitHub (pinned to a105acad6c)