gofiber/fiber · warning

cache: unexpected entry type %T for key %q

Error message

cache: unexpected entry type %T for key %q

What it means

Thrown at middleware/cache/manager.go:132 on the in-memory fallback path: memory.Get(key) returned a non-nil value whose Go type is not *item. The cache middleware expects every value in its private memory.Storage to be an *item; finding any other type means the store was populated by something else under a colliding key.

Source

Thrown at middleware/cache/manager.go:132

			return nil, fmt.Errorf("cache: failed to get key %q from storage: %w", m.logKey(key), err)
		}
		if raw == nil {
			return nil, errCacheMiss
		}

		it := m.acquire()
		if _, err := it.UnmarshalMsg(raw); err != nil {
			m.release(it)
			return nil, fmt.Errorf("cache: failed to unmarshal key %q: %w", m.logKey(key), err)
		}

		return it, nil
	}

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

	return nil, errCacheMiss
}

// get raw data from storage or memory
func (m *manager) 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("cache: failed to get raw key %q from storage: %w", m.logKey(key), err)
		}
		if raw == nil {
			return nil, errCacheMiss
		}
		return raw, nil

View on GitHub (pinned to 9a4c7e57fe)

Solutions

  1. Stop sharing one *memory.Storage instance across middleware that store different value types; let each middleware allocate its own (the default when Storage is nil).
  2. If sharing is intentional, partition the keyspace with distinct prefixes so types never collide on the same key.
  3. In tests, construct a fresh memory.Storage per middleware instance rather than reusing a global.
  4. Audit any custom code that calls .Set on the memory.Storage to ensure it only stores the type the owning middleware expects.

Example fix

// before (bug): one memory store shared across two middlewares
shared := memory.New()
cacheMgr := newManager(shared, false) // expects *item
csrfMgr  := newStorageManager(shared, false) // expects []byte -> collision

// after: each manager owns its private store
cacheMgr := newManager(nil, false)       // allocates private memory
csrfMgr  := newStorageManager(nil, false)
Defensive patterns

Strategy: type-guard

Validate before calling

// Ensure the cache middleware owns its memory store; never inject a shared one.
if cfg.Storage == nil {
    // newManager(nil, ...) allocates a private *memory.Storage - safe.
}

Type guard

// If you must read from a shared store, narrow the type before using it.
func asItem(v any) (*item, bool) {
    it, ok := v.(*item)
    return it, ok
}

Try / catch

raw := m.memory.Get(key)
if raw != nil {
    it, ok := raw.(*item)
    if !ok {
        // programming error - log loudly and treat as miss
        log.Printf("unexpected type %T in cache memory store", raw)
        return nil, errCacheMiss
    }
    _ = it
}

Prevention

When it happens

Trigger: Only possible when the cache middleware is NOT given an explicit Storage and instead uses its internally-allocated memory.Storage, yet that same *memory.Storage pointer is somehow shared with another middleware/component that writes a different Go type under the same key. In normal usage newManager allocates a private store so this never fires.

Common situations: Test contamination where a shared memory.Storage is reused across middleware instances in a test harness; hand-rolled wiring that injects a pre-populated memory.Storage into multiple managers; a fork that changed newManager to accept a shared store.

Related errors


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