{"record":{"id":"6161c6aea9789aba","repo":"microsoft/typescript-go","slug":"unexpected-message-type-d","errorCode":null,"errorMessage":"unexpected message type: %d","messagePattern":"unexpected message type: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/api/protocol_msgpack.go","lineNumber":90,"sourceCode":"\t\tmsg.Method = method\n\t\tmsg.Params = payload\n\tcase MessageTypeCallResponse:\n\t\t// Response to our Call - use method as ID\n\t\t// Note: Method must be empty for IsResponse() to return true\n\t\tid := jsonrpc.NewIDString(method)\n\t\tmsg.ID = id\n\t\tmsg.Result = payload\n\tcase MessageTypeCallError:\n\t\t// Error response to our Call\n\t\t// Note: Method must be empty for IsResponse() to return true\n\t\tid := jsonrpc.NewIDString(method)\n\t\tmsg.ID = id\n\t\tmsg.Error = &jsonrpc.ResponseError{\n\t\t\tCode:    jsonrpc.CodeInternalError,\n\t\t\tMessage: string(payload),\n\t\t}\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unexpected message type: %d\", msgType)\n\t}\n\n\treturn msg, nil\n}\n\nfunc (p *MessagePackProtocol) readTuple() (MessageType, string, []byte, error) {\n\t// Read fixed array marker (0x93 = 3-element array)\n\tt, err := p.r.ReadByte()\n\tif err != nil {\n\t\treturn 0, \"\", nil, err\n\t}\n\tif t != msgpackFixedArray3 {\n\t\treturn 0, \"\", nil, fmt.Errorf(\"%w: expected fixed 3-element array (0x93), received: 0x%02x\", ErrInvalidRequest, t)\n\t}\n\n\t// Read message type - can be positive fixint (0x00-0x7F) or uint8 (0xCC + value)\n\tt, err = p.r.ReadByte()\n\tif err != nil {","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/microsoft/typescript-go/blob/1bcfa18d79a3be41772223d5c05dfe4480e614ff/internal/api/protocol_msgpack.go#L72-L108","documentation":"ReadMessage parsed a valid tuple whose message type is one this reader never accepts from its peer: MessageTypeResponse, MessageTypeError, or MessageTypeCall. Only Request, CallResponse, and CallError are handled inbound; responses to this side's own Calls are consumed inline by SyncConn.Call, never by the main read loop.","triggerScenarios":"Both ends of the pipe wired in the same role (two 'servers' or two 'clients'), so each writes Call/Response frames toward the other; a client echoing a server-written frame back; loopback tests piping a side's output to its own input.","commonSituations":"Constructing the two protocol endpoints with swapped roles; test harnesses connecting a writer to itself; debugging proxies that reflect frames.","solutions":["Verify exactly one side owns SyncConn.Run and answers requests, the other issues them","Ensure the peer writes only request/call-response/call-error tuples toward this reader","In loopback tests, route each side's writer to the OTHER side's reader","Close and re-establish the connection after fixing wiring - the stream cannot be trusted"],"exampleFix":"// before\ngo server.Run(ctx); go server.Run(ctx) // both reading same role frames\n\n// after\ngo server.Run(ctx)          // one side serves\ngo clientLoop(ctx, clientConn) // other side calls","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := conn.Run(ctx); err != nil {\n\tif strings.Contains(err.Error(), \"unexpected message type\") {\n\t\t// role wiring is wrong or the peer echoed our own frames; rebuild the link\n\t\treturn rebuildLinkWithCorrectRoles()\n\t}\n\treturn err\n}","preventionTips":["Exactly one side runs SyncConn.Run; the other issues Calls","Route each side's writer to the other's reader in tests","Never echo received frames back verbatim"],"tags":["go","msgpack","protocol","message-type","wiring"],"backgroundTag":null,"analyzedSha":"1bcfa18d79a3be41772223d5c05dfe4480e614ff","analyzedAt":"2026-08-16T02:12:00.115Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}