{"record":{"id":"66df9c68fb302a5a","repo":"abhigyanpatwari/GitNexus","slug":"content-length-contentlength-exceeds-maximum-al","errorCode":null,"errorMessage":"Content-Length ${contentLength} exceeds maximum allowed size (${MAX_BUFFER_SIZE} bytes)","messagePattern":"Content-Length (.+?) exceeds maximum allowed size \\((.+?) bytes\\)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"gitnexus/src/mcp/compatible-stdio-transport.ts","lineNumber":156,"sourceCode":"\n    const headerText = this._readBuffer\n      .toString('utf8', 0, header.index)\n      .replace(/\\r\\n/g, '\\n')\n      .replace(/\\r/g, '\\n');\n    const match = headerText.match(/(?:^|\\n)content-length\\s*:\\s*(\\d+)/i);\n    if (!match) {\n      this.discardBufferedInput();\n      throw new Error('Missing Content-Length header from MCP client');\n    }\n\n    const contentLength = Number.parseInt(match[1], 10);\n    if (!Number.isFinite(contentLength) || contentLength < 0) {\n      this.discardBufferedInput();\n      throw new Error('Invalid Content-Length header from MCP client');\n    }\n    if (contentLength > MAX_BUFFER_SIZE) {\n      this.discardBufferedInput();\n      throw new Error(\n        `Content-Length ${contentLength} exceeds maximum allowed size (${MAX_BUFFER_SIZE} bytes)`,\n      );\n    }\n    const bodyStart = header.index + header.separatorLength;\n    const bodyEnd = bodyStart + contentLength;\n    if (this._readBuffer.length < bodyEnd) {\n      return null;\n    }\n\n    const body = this._readBuffer.toString('utf8', bodyStart, bodyEnd);\n    this._readBuffer = this._readBuffer.subarray(bodyEnd);\n    return deserializeMessage(body);\n  }\n\n  private readNewlineMessage(): JSONRPCMessage | null {\n    if (!this._readBuffer) {\n      return null;\n    }","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/aac7515d2a8c50a1f8f923c6fb77218b333560d6/gitnexus/src/mcp/compatible-stdio-transport.ts#L138-L174","documentation":"The stdio transport caps any single framed message at MAX_BUFFER_SIZE (10 MB, set in compatible-stdio-transport.ts) to prevent unbounded memory growth. When a declared Content-Length exceeds the cap it discards the buffered input and throws, so one oversized or corrupted length header cannot exhaust the server's memory.","triggerScenarios":"An MCP client sends a JSON-RPC request or tool-call whose framed body exceeds 10 MB — e.g. embedding a huge file's contents or a giant base64 blob in tool params — or a corrupted/garbage length header declares an enormous value; fuzzed stdin streams also trip it.","commonSituations":"Pasting an entire large file or dataset into a tool parameter; automated clients batching thousands of items into one request; proxies corrupting headers; hostile clients probing the transport's limits.","solutions":["Shrink the request: send file contents in chunks, batch tool params into smaller calls, or pass file paths instead of inline contents.","Strip accidentally embedded payloads (base64 images, minified bundles, lockfiles) from the request body.","If large messages are genuinely required in a private deployment, raise MAX_BUFFER_SIZE in a fork of compatible-stdio-transport.ts — upstream it stays 10 MB.","Restart the session afterward: buffered input was discarded, so the stream cannot resume mid-frame."],"exampleFix":"// before: one 40 MB request\nawait client.callTool({ name: 'context', arguments: { files: allFilesWithContents } });\n\n// after: chunked / path-based requests under the 10 MB frame cap\nfor (const batch of chunk(allFiles, 50)) {\n  await client.callTool({ name: 'context', arguments: { paths: batch.map(f => f.path) } });\n}","handlingStrategy":"validation","validationCode":"// Respect the transport's 10 MB frame cap before sending\nconst MCP_MAX_FRAME = 10 * 1024 * 1024;\n\nfunction assertSendable(msg: unknown): void {\n  const size = Buffer.byteLength(JSON.stringify(msg), 'utf8');\n  if (size > MCP_MAX_FRAME) {\n    throw new Error(`request body ${size} bytes exceeds MCP frame cap ${MCP_MAX_FRAME}`);\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await client.callTool(params);\n} catch (err) {\n  if (err instanceof Error && err.message.includes('exceeds maximum allowed size')) {\n    // split the work instead of retrying the same giant payload\n    for (const chunk of splitParams(params)) await client.callTool(chunk);\n    return;\n  }\n  throw err;\n}","preventionTips":["Pass file paths, not file contents, in tool parameters.","Batch tool arguments into bounded chunks (e.g. <= 100 items or <= 1 MB per request).","Strip base64 blobs and vendored file bodies from request payloads.","Treat the 10 MB cap as part of your contract; validate payload size client-side before sending."],"tags":["mcp","stdio-transport","payload-size","limits","content-length"],"backgroundTag":"payload-too-large","analyzedSha":"aac7515d2a8c50a1f8f923c6fb77218b333560d6","analyzedAt":"2026-08-20T23:29:22.980Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}