gofiber/fiber · error

cache: failed to marshal key %q: %w

Error message

cache: failed to marshal key %q: %w

What it means

Thrown at middleware/cache/manager.go:170 when it.MarshalMsg(nil) fails while serializing a cached item to msgp before writing it to storage. The item struct fields carry msgp `limit` tags (header value limit=16384, cache-control limit=2048, etc.); exceeding those caps, or an internal msgp encoding error, produces this. Marshal failures are rare because msgp encoding is deterministic for these types.

Source

Thrown at middleware/cache/manager.go:170

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

	return nil, errCacheMiss
}

// 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("cache: 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("cache: failed to store key %q: %w", m.logKey(key), err)
		}
		m.release(it)
		return nil
	}

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

// set data to storage or memory
func (m *manager) 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("cache: failed to store raw key %q: %w", m.logKey(key), err)

View on GitHub (pinned to 9a4c7e57fe)

Solutions

  1. Inspect the wrapped msgp error to see which field limit was exceeded (e.g. 'limit 16384 hit').
  2. Exclude the offending route from caching via Config.Next, or strip the oversized header before it enters the cached response.
  3. If the limit genuinely must be higher, regenerate msgp after editing the limit tag on the offending field in middleware/cache/manager.go and rebuild.
  4. Cap upstream response header sizes at the reverse proxy / origin so pathological values never reach the cache.

Example fix

// before: caching a route that returns multi-KB headers
app.Use(cache.New())

// after: skip caching for the offending route
app.Use(cache.New(cache.Config{
    Next: func(c fiber.Ctx) bool {
        return c.Path() == "/api/huge-headers"
    },
}))
Defensive patterns

Strategy: validation

Validate before calling

// Before caching a route, verify its responses don't exceed msgp field limits.
// header value limit=16384, cache-control limit=2048, etag limit=256.
func cacheable(resp *fasthttp.Response) bool {
    resp.Header.VisitAll(func(k, v []byte) {
        if len(v) > 16384 { /* will overflow; exclude from cache */ }
    })
    return true
}

Try / catch

raw, err := it.MarshalMsg(nil)
if err != nil {
    log.Printf("marshal failed for %q (likely oversized header): %v", key, err)
    m.release(it)
    return err // non-fatal upstream; route is excluded from cache via Next()
}

Prevention

When it happens

Trigger: An origin response carries a single header value larger than the 16384-byte msgp limit, a Cache-Control directive block larger than 2048 bytes, or an ETag larger than 256 bytes; the marshal step refuses to emit an oversized field.

Common situations: Upstream API returning very large Set-Cookie / Authorization / custom header values that get cached; misbehaving origin injecting a giant Cache-Control; values that grew after a backend change.

Related errors


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