{"record":{"id":"b48f23dcd9ee5b9f","repo":"deepseek-ai/deepseek-harness","slug":"client-connection-maxrequestbodybytes-string-ma","errorCode":null,"errorMessage":"client-connection maxRequestBodyBytes (${String(maxRequestBodyBytes)}) must be at least ${String(requiredImageBodyBytes)} for the configured aggregate image limit","messagePattern":"client-connection maxRequestBodyBytes \\((.+?)\\) must be at least (.+?) for the configured aggregate image limit","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/client/connection/src/index.ts","lineNumber":39,"sourceCode":"} from './rpc.ts'\nexport { HostConnectionService } from './rpc-host.ts'\n\nexport { API_PATH, HOST_EVENTS_PATH, MUX_EVENTS_PATH } from './api-path.ts'\n\n/** Stable Cordis plugin name. */\nexport const name = 'client-connection'\n\n/** Headroom for RPC JSON fields around aggregate base64 image payloads. */\nconst REQUEST_ENVELOPE_HEADROOM_BYTES = 1024 * 1024\n\nfunction assertImageBodyCapacity(ctx: Context, maxRequestBodyBytes: number): void {\n  const attachments = ctx.get('attachments')\n  if (attachments === undefined) return\n  const requiredImageBodyBytes = Math.ceil(\n    attachments.imageLimits.maxMessageImageBytes * 4 / 3,\n  ) + REQUEST_ENVELOPE_HEADROOM_BYTES\n  if (maxRequestBodyBytes < requiredImageBodyBytes) {\n    throw new Error(\n      `client-connection maxRequestBodyBytes (${String(maxRequestBodyBytes)}) must be at least `\n      + `${String(requiredImageBodyBytes)} for the configured aggregate image limit`,\n    )\n  }\n}\n\n/** Services required before providing Connection; API Proxy is an optional `/api` fallback. */\nexport const inject = ['webServer']\n\n/** Plugin config: the deployment's non-loopback serving authorities. */\nexport interface ConnectionConfig {\n  /**\n   * Authorities this deployment serves beyond loopback: exact `host:port`, or\n   * port-less `host` matching any port. The /api trust fence refuses any\n   * request whose Host is neither loopback nor listed here, so a\n   * non-loopback (`0.0.0.0`) deployment must declare the names it is reached\n   * by (the dsh CLI derives the machine's LAN IP literals itself). An entry\n   * that is not a bare, canonical authority fails the plugin load.","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/deepseek-ai/deepseek-harness/blob/b150a551b8d465e31e418e1b2eaf5e79bbb7d28e/packages/client/connection/src/index.ts#L21-L57","documentation":"At plugin apply, assertImageBodyCapacity checks that client-connection's maxRequestBodyBytes can carry one maximally image-laden request: the attachments service's aggregate maxMessageImageBytes inflates by 4/3 under base64, plus 1 MiB of JSON envelope headroom (REQUEST_ENVELOPE_HEADROOM_BYTES). A body cap under that floor fails the load immediately, so the first large image upload cannot die later as an opaque 413.","triggerScenarios":"Loading client-connection with maxRequestBodyBytes set below ceil(maxMessageImageBytes * 4/3) + 1048576, or raising the attachments image limit without raising the body cap to match.","commonSituations":"Hardening passes shrink maxRequestBodyBytes and forget the image budget; a deployment raises maxMessageImageBytes to accept large screenshots and the old body cap now undercuts it.","solutions":["Raise maxRequestBodyBytes to at least ceil(maxMessageImageBytes * 4/3) + 1048576 (the defaults satisfy this)","Or lower the attachments image limit so the existing body cap covers the base64-expanded worst case","Change both knobs in the same config review so the inequality always holds"],"exampleFix":"# before — body cap below the image budget\nclient-connection:\n  maxRequestBodyBytes: 104857600        # 100 MiB\nattachments:\n  imageLimits:\n    maxMessageImageBytes: 201326592     # 192 MiB → throws\n\n# after\nclient-connection:\n  maxRequestBodyBytes: 269484032        # ≥ 192 MiB × 4/3 + 1 MiB","handlingStrategy":"validation","validationCode":"const REQUEST_ENVELOPE_HEADROOM_BYTES = 1024 * 1024\nconst required = Math.ceil(imageLimits.maxMessageImageBytes * 4 / 3) + REQUEST_ENVELOPE_HEADROOM_BYTES\nif (config.maxRequestBodyBytes < required) {\n  throw new Error(`raise maxRequestBodyBytes to at least ${required} for the configured image limit`)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat the two limits as coupled: recompute the floor whenever either changes","Prefer the defaults unless a concrete constraint forces a change","Run a config preflight asserting the inequality before deploying"],"tags":["config","limits","validation","upload","images"],"backgroundTag":"config-limit-mismatch","analyzedSha":"b150a551b8d465e31e418e1b2eaf5e79bbb7d28e","analyzedAt":"2026-08-24T18:12:29.105Z","schemaVersion":2},"datasetVersion":"2026-08-24T22:17:12.610Z"}