abhigyanpatwari/GitNexus · error · Error

Invalid Content-Length header from MCP client

Error message

Invalid Content-Length header from MCP client

What it means

Defensive validation in the stdio transport's frame parser: after the content-length regex captures a digit run, the value must parse to a finite, non-negative integer. Because the regex only captures \d+, ordinary malformed headers fail earlier as 'Missing Content-Length header'; this branch catches degenerate values such as a digit string so long that parseInt yields Infinity.

Source

Thrown at gitnexus/src/mcp/compatible-stdio-transport.ts:152

    const header = findHeaderEnd(this._readBuffer);
    if (header === null) {
      return null;
    }

    const headerText = this._readBuffer
      .toString('utf8', 0, header.index)
      .replace(/\r\n/g, '\n')
      .replace(/\r/g, '\n');
    const match = headerText.match(/(?:^|\n)content-length\s*:\s*(\d+)/i);
    if (!match) {
      this.discardBufferedInput();
      throw new Error('Missing Content-Length header from MCP client');
    }

    const contentLength = Number.parseInt(match[1], 10);
    if (!Number.isFinite(contentLength) || contentLength < 0) {
      this.discardBufferedInput();
      throw new Error('Invalid Content-Length header from MCP client');
    }
    if (contentLength > MAX_BUFFER_SIZE) {
      this.discardBufferedInput();
      throw new Error(
        `Content-Length ${contentLength} exceeds maximum allowed size (${MAX_BUFFER_SIZE} bytes)`,
      );
    }
    const bodyStart = header.index + header.separatorLength;
    const bodyEnd = bodyStart + contentLength;
    if (this._readBuffer.length < bodyEnd) {
      return null;
    }

    const body = this._readBuffer.toString('utf8', bodyStart, bodyEnd);
    this._readBuffer = this._readBuffer.subarray(bodyEnd);
    return deserializeMessage(body);
  }

View on GitHub (pinned to aac7515d2a)

Solutions

  1. Fix the client to compute Content-Length from Buffer.byteLength of the serialized body and to validate Number.isFinite before writing.
  2. Replace hand-rolled framing with the official MCP SDK transport.
  3. Restart the session: the parser already discarded all buffered input, so the connection state is unrecoverable.
  4. If fuzzing/testing intentionally, feed well-formed frames instead.

Example fix

// before: length computed from a possibly non-finite value
const len = maybeCorruptedCounter;
sock.write(`Content-Length: ${len}\r\n\r\n` + body);

// after: derive from serialized bytes and validate before writing
const buf = Buffer.from(JSON.stringify(msg), 'utf8');
if (!Number.isFinite(buf.length) || buf.length < 0) throw new Error('bad length');
sock.write(`Content-Length: ${buf.length}\r\n\r\n`);
sock.write(buf);
Defensive patterns

Strategy: validation

Validate before calling

// Validate a length before it ever reaches the wire
function frame(msg: unknown): Buffer {
  const body = Buffer.from(JSON.stringify(msg), 'utf8');
  const len = body.length;
  if (!Number.isFinite(len) || len < 0 || !Number.isInteger(len)) {
    throw new Error(`computed invalid Content-Length: ${len}`);
  }
  return Buffer.concat([Buffer.from(`Content-Length: ${len}\r\n\r\n`), body]);
}

Try / catch

try {
  await transport.handleData(chunk);
} catch (err) {
  const msg = err instanceof Error ? err.message : String(err);
  if (msg.includes('Invalid Content-Length')) {
    // stream already discarded — treat the session as corrupt and restart it
    await restartMcpSession();
    return;
  }
  throw err;
}

Prevention

When it happens

Trigger: Corrupted or fuzzed stdin bytes that happen to form a header terminator plus a content-length line with an astronomically long digit run (overflowing Number to Infinity); a broken client or test harness computing the header value in a way that produces a non-representable number; memory-corrupted pipes writing garbage.

Common situations: Fuzzing the transport with random bytes; a client bug that stringifies NaN/Infinity into a length computation despite the digit-only regex; almost never seen with SDK-based clients — its appearance almost always indicates a broken hand-rolled client or corrupted stream.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@aac7515d2a (2026-08-20). Data as JSON: /api/errors/931a75d43a797acf. Report an issue: GitHub.