gofiber/fiber · error

failed to write cached response while locked

Error message

failed to write cached response while locked: %w

What it means

Wraps an error from maybeWriteCachedResponse when re-checking the cache after acquiring the lock (double-checked locking pattern). Same underlying causes as errors 168/169 (storage read or unmarshal failure), but observed on the locked path — meaning another request may have just written or be writing the entry.

Solutions

  1. Address the storage/marshalling root cause (errors 168/169).
  2. If a concurrent writer is producing bad blobs, gate writes behind the same schema version.
  3. Investigate lock-holder interactions — ensure Unlock is always called (the deferred Unlock logs but does not propagate).
  4. Add tracing on the locked re-check path to correlate with concurrent writers.
Defensive patterns

Strategy: retry

Prevention

When it happens

Trigger: After cfg.Lock.Lock succeeds, the second maybeWriteCachedResponse call returns an error. Common when the storage briefly failed on the fastpath (error 170) and is still failing under the lock, or when a concurrent writer produced an unparseable blob that this holder then reads.

Common situations: Storage outage that spans both lookups, a race where a concurrent process wrote a schema-incompatible blob, or a storage backend under heavy load returning partial/corrupt reads.

Related errors


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

Appendix: source

Thrown at middleware/idempotency/idempotency.go:136

		// First-pass: if the idempotency key is in the storage, get and return the response
		if ok, err := maybeWriteCachedResponse(c, key); err != nil {
			return fmt.Errorf("failed to write cached response at fastpath: %w", err)
		} else if ok {
			return nil
		}

		if err := cfg.Lock.Lock(key); err != nil {
			return fmt.Errorf("failed to lock: %w", err)
		}
		defer func() {
			if err := cfg.Lock.Unlock(key); err != nil {
				log.Errorf("[IDEMPOTENCY] failed to unlock key %q: %v", maskKey(key), err)
			}
		}()

		// Lock acquired. If the idempotency key now is in the storage, get and return the response
		if ok, err := maybeWriteCachedResponse(c, key); err != nil {
			return fmt.Errorf("failed to write cached response while locked: %w", err)
		} else if ok {
			return nil
		}

		// Execute the request handler
		if err := c.Next(); err != nil {
			// If the request handler returned an error, return it and skip idempotency
			return err
		}

		// Construct response
		res := &response{
			StatusCode: c.Response().StatusCode(),
			Body:       c.Response().Body(),
		}
		{
			headers := make(map[string][]string)
			if err := c.Bind().RespHeader(headers); err != nil {

View on GitHub (pinned to a105acad6c)