gofiber/fiber · warning
csrf: unexpected value type %T in storage
Error message
csrf: unexpected value type %T in storage
What it means
Thrown at middleware/csrf/storage_manager.go:48 on the in-memory fallback path: memory.Get(key) returned a non-nil value whose Go type is not []byte. The CSRF storage manager expects byte slices in its private memory.Storage; any other type means the store was contaminated by another writer under a colliding key.
Source
Thrown at middleware/csrf/storage_manager.go:48
storageManager.memory = memory.New()
}
return storageManager
}
// get raw data from storage or memory
func (m *storageManager) getRaw(ctx context.Context, key string) ([]byte, error) {
if m.storage != nil {
raw, err := m.storage.GetWithContext(ctx, key)
if err != nil {
return nil, fmt.Errorf("csrf: failed to get value from storage: %w", err)
}
return raw, nil
}
if value := m.memory.Get(key); value != nil {
raw, ok := value.([]byte)
if !ok {
return nil, fmt.Errorf("csrf: unexpected value type %T in storage", value)
}
return raw, nil
}
return nil, nil
}
// set data to storage or memory
func (m *storageManager) setRaw(ctx context.Context, key string, raw []byte, exp time.Duration) error {
if m.storage != nil {
if err := m.storage.SetWithContext(ctx, key, raw, exp); err != nil {
return fmt.Errorf("csrf: failed to store key %q: %w", m.logKey(key), err)
}
return nil
}
m.memory.Set(key, raw, exp)
return nilView on GitHub (pinned to 9a4c7e57fe)
Solutions
- Stop sharing one *memory.Storage across middlewares that store different types; let CSRF allocate its own (default when Storage is nil).
- Namespace keys with distinct prefixes if sharing a store is unavoidable.
- Reset memory.Storage between tests to avoid cross-test contamination.
- Audit every .Set call on the shared store to ensure only []byte values land on CSRF keys.
Example fix
// before (bug): shared store across CSRF and another component
shared := memory.New()
app.Use(csrf.New(csrf.Config{ /* injects shared via custom wiring */ }))
// after: each middleware owns its private store
app.Use(csrf.New()) // Storage nil -> private memory.Storage, no type collision Defensive patterns
Strategy: type-guard
Validate before calling
// Ensure CSRF owns its memory store; don't inject a shared one.
if cfg.Storage == nil && cfg.Session == nil {
// newStorageManager(nil, ...) allocates a private *memory.Storage - safe.
} Type guard
func asCSRFBytes(v any) ([]byte, bool) {
b, ok := v.([]byte)
return b, ok
} Try / catch
if v := m.memory.Get(key); v != nil {
raw, ok := v.([]byte)
if !ok {
// programming error - log loudly, treat as no token
log.Printf("unexpected csrf value type %T", v)
return nil, nil
}
return raw, nil
} Prevention
- Allocate a private memory.Storage per CSRF middleware (Storage: nil).
- Never share memory stores across middlewares with different value types.
- Reset memory stores between tests.
- Namespace keys if sharing a store is truly unavoidable.
When it happens
Trigger: Only fires when CSRF is configured without an explicit Storage (so it allocates its own memory.Storage) AND that same store pointer is shared with another component writing non-[]byte values under colliding keys. The default newStorageManager allocates a private store, so this should never occur in normal wiring.
Common situations: Test harness sharing one memory.Storage across cache + CSRF middlewares; custom fork that injects a shared store; deliberate key-prefix reuse across components during development.
Related errors
- cache: unexpected entry type %T for key %q
- cache: unexpected raw entry type %T for key %q
- csrf: failed to fetch token from storage: %w
- csrf: failed to store token in storage: %w
- csrf: failed to delete token from storage: %w
AI-assisted analysis of gofiber/fiber@9a4c7e57fe (2026-08-04).
Data as JSON: /data/errors/cb4261690dc15b37.json.
Report an issue: GitHub.