{"record":{"id":"d4973c9234228f03","repo":"XTLS/Xray-core","slug":"write-packet-data-w","errorCode":null,"errorMessage":"write packet data: %w","messagePattern":"write packet data: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"transport/internet/finalmask/xmc/protocol.go","lineNumber":389,"sourceCode":"\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"read byte: %w\", err)\n\t}\n\n\treturn buf[0], nil\n}\n\nfunc writePacket(w io.Writer, packetID int, fields ...field) error {\n\t_, err := writePacketWithLength(w, packetID, fields...)\n\treturn err\n}\n\nfunc writePacketWithLength(w io.Writer, packetID int, fields ...field) (int, error) {\n\tframe, err := encodePacket(packetID, fields...)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tif err = writeFull(w, frame); err != nil {\n\t\treturn 0, fmt.Errorf(\"write packet data: %w\", err)\n\t}\n\treturn len(frame), nil\n}\n\nfunc encodePacket(packetID int, fields ...field) ([]byte, error) {\n\tvar dataBuf bytes.Buffer\n\n\tfor _, field := range fields {\n\t\terr := field.writeTo(&dataBuf)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"write packet field: %w\", err)\n\t\t}\n\t}\n\tif dataBuf.Len() > maxPacketDataLength {\n\t\treturn nil, fmt.Errorf(\"write packet: bad length: %d\", dataBuf.Len())\n\t}\n\n\tpacketIDVarint := Varint(packetID)","sourceCodeStart":371,"sourceCodeEnd":407,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/transport/internet/finalmask/xmc/protocol.go#L371-L407","documentation":"writePacketWithLength encodes all fields into a frame and then writes it atomically with writeFull; this error wraps that final write failing. It is the outermost write error for any outbound packet, so any underlying connection problem (closed, reset, deadline) shows up here after the frame was built successfully.","triggerScenarios":"writePacket on a connection the peer already closed; write deadline exceeded while flushing a large frame; conn closed locally by error handling while a packet send was queued.","commonSituations":"Sending keepalive/login packets right as the server drops the connection; slow links where big padded frames exceed deadlines; races between connection teardown and pending sends.","solutions":["Once writePacketWithLength returns this error, treat the connection as dead — do not retry on the same conn.","Classify the wrapped error (closed vs timeout vs reset) for metrics/alerting.","Size write deadlines to your largest padded frame.","Route sends through a single writer goroutine to avoid close/write races."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if _, err := writePacketWithLength(w, id, fields...); err != nil {\n    teardownConn()\n    var nerr net.Error\n    if errors.As(err, &nerr) && nerr.Timeout() {\n        return fmt.Errorf(\"frame flush timed out (deadline too small?): %w\", err)\n    }\n    return fmt.Errorf(\"connection lost while sending packet %d: %w\", id, err)\n}","preventionTips":["Treat any writePacketWithLength failure as fatal for the connection; reconnect rather than retry on the same conn.","Set write deadlines covering your largest padded frame.","Export metrics split by closed/timeout/reset to monitor transport health."],"tags":["go","network","io","protocol-framing"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}