{"record":{"id":"144f9ebf32117c95","repo":"XTLS/Xray-core","slug":"write-padding-turn-d-w","errorCode":null,"errorMessage":"write padding turn %d: %w","messagePattern":"write padding turn (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"transport/internet/finalmask/xmc/padding.go","lineNumber":62,"sourceCode":"\tsendVariants        []int\n}\n\nfunc runPaddingSchedule(reader io.Reader, writer io.Writer, isClient bool, firstTurnPrefixLength int, schedule []paddingTurn) error {\n\tif err := validatePaddingSchedule(schedule, firstTurnPrefixLength); err != nil {\n\t\treturn err\n\t}\n\n\tvar writeBuffer []byte\n\tfor i, turn := range schedule {\n\t\tprefixLength := 0\n\t\tif i == 0 {\n\t\t\tprefixLength = firstTurnPrefixLength\n\t\t}\n\n\t\tlocalSends := isClient == (turn.direction == paddingClientToServer)\n\t\tif localSends {\n\t\t\tif err := writePaddingTurnWithBuffer(writer, turn, prefixLength, time.Sleep, &writeBuffer); err != nil {\n\t\t\t\treturn fmt.Errorf(\"write padding turn %d: %w\", i, err)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif err := readPaddingTurn(reader, turn, prefixLength); err != nil {\n\t\t\treturn fmt.Errorf(\"read padding turn %d: %w\", i, err)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc validatePaddingSchedule(schedule []paddingTurn, firstTurnPrefixLength int) error {\n\tif len(schedule) == 0 {\n\t\treturn fmt.Errorf(\"empty padding schedule\")\n\t}\n\tif firstTurnPrefixLength < 0 {\n\t\treturn fmt.Errorf(\"negative first turn prefix length: %d\", firstTurnPrefixLength)\n\t}\n\tif firstTurnPrefixLength > 0 && schedule[0].direction != paddingClientToServer {","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/transport/internet/finalmask/xmc/padding.go#L44-L80","documentation":"runPaddingSchedule failed while locally writing padding turn i to imitate Minecraft 1.26.12 traffic shape. The wrapped error is either an I/O failure writing a padding chunk, or a randomness/variant-selection error inside writePaddingTurnWithBuffer (e.g. bad delay range, chunk shorter than the length header).","triggerScenarios":"The local endpoint sends its padding turns and the connection breaks mid-write; the schedule's turn definition is internally inconsistent so chunk generation produces invalid records (code-level bug in the schedule definition).","commonSituations":"Peer disconnects during the handshake padding phase; firewall RSTs on the bursty padding pattern; custom padding schedules added by forks with invalid chunk/delay parameters.","solutions":["Check the wrapped error: 'write padding chunk N' indicates transport failure (reconnect); other messages indicate schedule-definition bugs","If you maintain schedules, run them through validatePaddingSchedule-equivalent checks plus a dry-run writer in tests","Verify both endpoints use the same hardcoded schedule (same library version)"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"err := runPaddingSchedule(...)\nif err != nil && strings.Contains(err.Error(), \"write padding turn\") {\n    // transport died mid-shaping or schedule bug; reconnect or fix schedule\n    return err\n}","preventionTips":["Dry-run new schedules against an io.Discard writer in tests","Validate schedule definitions with validatePaddingSchedule before shipping","Keep both endpoints on the same schedule version"],"tags":["go","network","padding","handshake","traffic-shaping"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}