Skip to content

fix(protocol): size RESP payload cap from --storage-max-value and reply gracefully on oversize - #31

Merged
christianparpart merged 1 commit into
masterfrom
fix/resp-large-payload-cap
Jul 9, 2026
Merged

fix(protocol): size RESP payload cap from --storage-max-value and reply gracefully on oversize#31
christianparpart merged 1 commit into
masterfrom
fix/resp-large-payload-cap

Conversation

@christianparpart

Copy link
Copy Markdown
Member

Problem

The RESP2 handler capped a single bulk string at a hard-coded 64 MiB and, on exceeding it, closed the connection with no reply — the client saw a bare TCP reset (ECONNRESET / WSA 10054). Two consequences:

  1. A client storing a value larger than 64 MiB (e.g. sccache pushing a large compiled object into the cache) had its connection abruptly reset mid-command, failing the operation.
  2. Raising --storage-max-value above 64 MiB had no effect: the wire-layer cap fired before the (configurable, graceful) storage-layer cap could.

Fix

  • The payload cap is now per-session and tracks the configured max value. Replaced the hard-coded MaxPayloadBytes constant with SessionContext::maxPayloadBytes (default: the 64 MiB floor). The daemon raises it to max(floor, storageMaxValueBytes), so --storage-max-value drives both the wire and the storage limit from one knob — any value the cache will store can also be received off the wire.
  • Graceful error instead of a bare reset. On a parse error other than Truncated (a genuine protocol violation: PayloadTooLarge / MalformedFrame / LineTooLong), the handler now replies -ERR Protocol error: … before closing, mirroring Redis. A Truncated frame (peer hung up mid-message) still just drops — there is nothing to reply to.

Tests

  • New RESP regression tests: a value within the per-session cap is stored (+OK); a value exceeding it now receives -ERR Protocol error: … rather than an abrupt close.
  • Full [protocol] suite green: 2070 assertions, 326 cases.

https://claude.ai/code/session_01ERPincVQJuZoWhE77VSWTh

…ly on oversize

The RESP2 handler capped a single bulk string at a hard-coded 64 MiB and, on
exceeding it, dropped the connection with no reply. A client storing a value
larger than 64 MiB (e.g. a build cache pushing a large object) therefore saw an
abrupt TCP reset, and raising --storage-max-value above 64 MiB had no effect
because the wire cap fired first.

- Replace the hard-coded MaxPayloadBytes constant with
  SessionContext::maxPayloadBytes (default: the 64 MiB floor). The daemon raises
  it to max(floor, storageMaxValueBytes), so --storage-max-value now drives both
  the wire and the storage limit from one knob: any value the cache will store
  can also be received off the wire.
- On a parse error other than Truncated (a genuine protocol violation such as
  PayloadTooLarge / MalformedFrame / LineTooLong) reply "-ERR Protocol error: ..."
  before closing, mirroring Redis, instead of a bare connection reset. A
  Truncated frame (peer hung up mid-message) still just drops.
- Add RESP regression tests for the per-session cap and the graceful error reply.

Signed-off-by: Christian Parpart <c.parpart@lastrada.net>
Claude-Session: https://claude.ai/code/session_01ERPincVQJuZoWhE77VSWTh
@christianparpart
christianparpart force-pushed the fix/resp-large-payload-cap branch from 46c714f to 2d055e9 Compare July 9, 2026 07:10
@christianparpart
christianparpart merged commit 701abbc into master Jul 9, 2026
11 checks passed
@christianparpart
christianparpart deleted the fix/resp-large-payload-cap branch July 9, 2026 07:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant