Redis failure-mode coverage in 3 middleware sites — class-of-bugs fix

2026-05-07

apimiddlewareredis

What We Built

Three middleware sites had if (redis) { await redis.X(); ... } blocks with no try/catch. If Redis was unavailable they fell through to in-memory; if Redis threw, the unhandled exception propagated as middleware 500. Wrapped each block in try/catch that falls back to the existing in-memory or fail-open path.

Why It Matters

Predicted by user memory feedback_redis_failure_modes.md: Redis-using code must guard BOTH getRedis() === undefined AND redis.X() throws. PR #176 fixed only the latter for auth; this PR addressed all three remaining sites in one class-of-bugs sweep.

How It Works

Three regression tests, one per finding, each mocks getRedis to return an object whose method throws. Asserts the middleware does NOT return 500 — falls through to in-memory rate limiter / fail-open default.

Lockstep Checklist

  • [x] No API route changes (middleware/internal — lockstep N/A)
  • [x] No SDK changes
  • [x] No MCP tool changes
  • [x] Regression test included (test-first invariant per /quality-fleet protocol)
  • [x] Linked to /quality-fleet R1 dashboard at .quality/dashboard.md

Provenance

Auto-found by /quality-fleet R1 (2026-05-07) scanner round, fixed in fix-agent batch under "go for all of it" autonomy grant. PR #205 merged to main as commit e74a38d38. Finding(s) tracked at .quality/findings.jsonl (entries: "b2c3d4e5f6a7", "c3d4e5f6a7b8", "d4e5f6a7b8c9"). Production-deployed via ECS task-def revision 732 series.