gofiber/fiber · error

cache: failed to marshal key

Error message

cache: failed to marshal key %q: %w

What it means

Returned by manager.set when it.MarshalMsg fails while serializing a cache item before storing it externally. MarshalMsg can fail because the item struct declares msgp field limits (e.g. value limit=16384, headers limit=1024) that reject oversized fields.

Solutions

  1. Identify which header/field is oversized by inspecting the response being cached (the wrapped msgp error often names the offending field).
  2. Exclude the offending header from caching via the cache middleware's header-ignore configuration if its value is not cache-relevant.
  3. Do not cache responses known to carry oversized header payloads (set a cache-control: no-store or skip these routes).
  4. If the limit genuinely must be higher, it requires regenerating the msgp code with raised limits — not a runtime config.

Example fix

// before: caching a route that emits an oversized header
app.Get("/blob", emitHugeHeaderHandler, cache.New())

// after: opt that route out of caching
app.Get("/blob", emitHugeHeaderHandler) // no cache.New()
Defensive patterns

Strategy: validation

Validate before calling

// Validate the response is cache-safe (no oversized headers) BEFORE storing.
const maxHeaderValue = 16384 // matches cachedHeader.value msgp limit

func headerWithinLimits(h *fasthttp.ResponseHeader) error {
    var offender string
    h.VisitAll(func(k, v []byte) {
        if len(v) > maxHeaderValue {
            offender = string(k)
        }
    })
    if offender != "" {
        return fmt.Errorf("header %s exceeds %d-byte cache limit", offender, maxHeaderValue)
    }
    return nil
}

Try / catch

if err := headerWithinLimits(respHdr); err != nil {
    log.Warn("skipping cache for oversized response:", err)
    // do not cache this response
} else {
    _ = manager.set(ctx, key, it, exp)
}

Prevention

When it happens

Trigger: Caching a response whose header value exceeds the 16384-byte limit, with more than 1024 headers, a content-type over 256 bytes, cache-control over 2048 bytes, etc.; any single cachedHeader field breaching its declared msgp field limit during encode.

Common situations: Handlers that echo very large header values (long Set-Cookie, oversized Link/Content-Security-Policy, base64-encoded blobs in headers); responses with hundreds of headers; upstream proxies injecting massive header blocks. Memory-Storage mode never marshals, so this is external-Storage only.

Related errors


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

Appendix: 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 a105acad6c)