microsoft/typescript-go · error · ErrInvalidRequest

%w: expected fixed 3-element array (0x93), received: 0x%02x

Error message

%w: expected fixed 3-element array (0x93), received: 0x%02x

What it means

The first byte of every frame must be the msgpack fixed-array-3 marker 0x93 because each message is a [type, method, payload] tuple. Anything else means the byte stream is not aligned to a message boundary - desynchronized, corrupted, or an entirely different wire format. Wraps ErrInvalidRequest so it is detectable with errors.Is.

Source

Thrown at internal/api/protocol_msgpack.go:103

		msg.Error = &jsonrpc.ResponseError{
			Code:    jsonrpc.CodeInternalError,
			Message: string(payload),
		}
	default:
		return nil, fmt.Errorf("unexpected message type: %d", msgType)
	}

	return msg, nil
}

func (p *MessagePackProtocol) readTuple() (MessageType, string, []byte, error) {
	// Read fixed array marker (0x93 = 3-element array)
	t, err := p.r.ReadByte()
	if err != nil {
		return 0, "", nil, err
	}
	if t != msgpackFixedArray3 {
		return 0, "", nil, fmt.Errorf("%w: expected fixed 3-element array (0x93), received: 0x%02x", ErrInvalidRequest, t)
	}

	// Read message type - can be positive fixint (0x00-0x7F) or uint8 (0xCC + value)
	t, err = p.r.ReadByte()
	if err != nil {
		return 0, "", nil, err
	}
	var rawType byte
	if t <= 0x7F {
		// Positive fixint - the byte IS the value
		rawType = t
	} else if t == msgpackU8 {
		// uint8 marker - next byte is the value
		rawType, err = p.r.ReadByte()
		if err != nil {
			return 0, "", nil, err
		}
	} else {

View on GitHub (pinned to 1bcfa18d79)

Solutions

  1. Confirm both endpoints were built with NewMessagePackProtocol over the same transport
  2. Ensure exactly one bufio.Reader wraps the connection; sharing it desyncs offsets
  3. When bridging from JSON/LSP, write an explicit translator rather than raw passthrough
  4. Inspect the offending byte: 0x7b ('{') indicates JSON framing; 0x43 indicates 'Content-Length:' headers

Example fix

// before
r := bufio.NewReader(conn); r2 := bufio.NewReader(conn) // two readers!

// after
br := bufio.NewReader(conn)
proto := api.NewMessagePackProtocol(readWriter{Reader: br, Writer: conn})
Defensive patterns

Strategy: try-catch

Try / catch

err := proto.ReadMessage()
if err != nil && errors.Is(err, api.ErrInvalidRequest) {
	// framing desync: the byte stream cannot be recovered; close the connection
	log.Printf("protocol desync: %v", err)
	conn.Close()
}

Prevention

When it happens

Trigger: A prior partial read left stray bytes; the peer speaks plain JSON-RPC or LSP Content-Length framing on this connection; two bufio.Readers sharing one conn stealing bytes from each other.

Common situations: Mixing protocol implementations on one pipe; proxies mangling bytes; constructing the protocol over a conn that something else also reads.

Related errors


AI-assisted analysis of microsoft/typescript-go@1bcfa18d79 (2026-08-16). Data as JSON: /api/errors/131a5627c467c33b. Report an issue: GitHub.