chenhg5/cc-connect · error

invalid Content-Length: %w

Error message

invalid Content-Length: %w

What it means

The header line 'Content-Length: <val>' was found but its value could not be parsed as an integer (strconv.Atoi failed). The copilot peer sent a malformed Content-Length header, violating the LSP framing protocol, so the message cannot be framed or read safely.

Source

Thrown at agent/copilot/jsonrpc.go:104

// readMessage reads one Content-Length framed message and returns the raw JSON body.
func (lr *lspReader) readMessage() ([]byte, error) {
	contentLength := -1
	for {
		line, err := lr.reader.ReadString('\n')
		if err != nil {
			return nil, fmt.Errorf("read header: %w", err)
		}
		line = strings.TrimRight(line, "\r\n")
		if line == "" {
			// End of headers
			break
		}
		if strings.HasPrefix(line, "Content-Length: ") {
			val := strings.TrimPrefix(line, "Content-Length: ")
			n, err := strconv.Atoi(strings.TrimSpace(val))
			if err != nil {
				return nil, fmt.Errorf("invalid Content-Length: %w", err)
			}
			contentLength = n
		}
		// Ignore other headers (Content-Type, etc.)
	}

	if contentLength < 0 {
		return nil, fmt.Errorf("missing Content-Length header")
	}
	if contentLength > 10*1024*1024 {
		return nil, fmt.Errorf("Content-Length too large: %d", contentLength)
	}

	body := make([]byte, contentLength)
	if _, err := io.ReadFull(lr.reader, body); err != nil {
		return nil, fmt.Errorf("read body: %w", err)
	}
	return body, nil

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Check whether the copilot binary or a wrapper script pollutes stdout with non-LSP output and route logs to stderr
  2. Upgrade/downgrade the copilot CLI to a conforming version
  3. Test with runMockCopilot to reproduce the exact header bytes being sent
  4. If a wrapper is used, strip non-LSP lines before they reach the framing reader

Example fix

// before (mock emits bad header)
fmt.Fprintf(w, "Content-Length: %s\r\n\r\n", len(body)) // %s on int -> bad
// after
fmt.Fprintf(w, "Content-Length: %d\r\n\r\n", len(body))
Defensive patterns

Strategy: validation

Validate before calling

// validate a header line before parsing
func parseContentLength(line string) (int, error) {
    val := strings.TrimSpace(strings.TrimPrefix(line, "Content-Length: "))
    if val == "" { return 0, errors.New("empty Content-Length") }
    n, err := strconv.Atoi(val)
    if err != nil || n < 0 { return 0, fmt.Errorf("bad Content-Length %q", val) }
    return n, nil
}

Try / catch

if _, err := reader.readMessage(); err != nil && strings.Contains(err.Error(), "invalid Content-Length") {
    slog.Error("peer sent malformed LSP header — check for stdout pollution", "err", err)
    // fail fast; do not attempt to resync framing
}

Prevention

When it happens

Trigger: readMessage parsing a header like 'Content-Length: abc' or with garbage after the number from the copilot process stdout — emitted when a non-conforming CLI writes junk to stdout.

Common situations: A copilot CLI version (or wrapper script) printing log lines interleaved with LSP frames on stdout; a mock/debug shim emitting malformed headers; locale/encoding issues injecting characters into the header.

Understand the failure class

Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/cce2f69d59a5b548. Report an issue: GitHub.