{"record":{"id":"480afa2dc2d79900","repo":"ginuerzh/gost","slug":"write-data-maximum-exceeded","errorCode":null,"errorMessage":"write: data maximum exceeded","messagePattern":"write: data maximum exceeded","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"relay.go","lineNumber":325,"sourceCode":"\tdlen := int(binary.BigEndian.Uint16(bb[:]))\n\tif len(b) >= dlen {\n\t\treturn io.ReadFull(c.Conn, b[:dlen])\n\t}\n\tbuf := make([]byte, dlen)\n\t_, err = io.ReadFull(c.Conn, buf)\n\tn = copy(b, buf)\n\treturn\n}\n\nfunc (c *relayConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {\n\tn, err = c.Read(b)\n\taddr = c.Conn.RemoteAddr()\n\treturn\n}\n\nfunc (c *relayConn) Write(b []byte) (n int, err error) {\n\tif len(b) > 0xFFFF {\n\t\terr = errors.New(\"write: data maximum exceeded\")\n\t\treturn\n\t}\n\tn = len(b) // force byte length consistent\n\tif c.wbuf.Len() > 0 {\n\t\tif c.udp {\n\t\t\tvar bb [2]byte\n\t\t\tbinary.BigEndian.PutUint16(bb[:2], uint16(len(b)))\n\t\t\tc.wbuf.Write(bb[:])\n\t\t\tc.headerSent = true\n\t\t}\n\t\tc.wbuf.Write(b) // append the data to the cached header\n\t\t// _, err = c.Conn.Write(c.wbuf.Bytes())\n\t\t// c.wbuf.Reset()\n\t\t_, err = c.wbuf.WriteTo(c.Conn)\n\t\treturn\n\t}\n\n\tif !c.udp {","sourceCodeStart":307,"sourceCodeEnd":343,"githubUrl":"https://github.com/ginuerzh/gost/blob/a33fdbf4c98034f4bfeeaea9868909822b9c526d/relay.go#L307-L343","documentation":"relayConn.Write buffers data to be relayed and prefixes it with a 2-byte length, so payloads are limited to 0xFFFF (65535) bytes. A Write with a larger buffer cannot be framed and is rejected before any bytes are queued.","triggerScenarios":"Calling Write (directly or via io.Copy / WriteTo) with a slice longer than 65535 bytes on a relayConn.","commonSituations":"Large reads from a source conn (io.Copy with a >64KB buffer) piped into the relay connection without chunking.","solutions":["Write in chunks of at most 0xFFFF bytes","Reduce the read/copy buffer size to <= 64KB","If you own the relay protocol, ensure both ends agree on the framing limit"],"exampleFix":"// before\nbuf := make([]byte, 128*1024)\nn, _ := src.Read(buf)\nrelay.Write(buf[:n]) // fails when n > 65535\n// after\nconst maxChunk = 0xFFFF\nfor len(data) > 0 {\n    c := data\n    if len(c) > maxChunk { c = c[:maxChunk] }\n    if _, err := relay.Write(c); err != nil { return err }\n    data = data[len(c):]\n}","handlingStrategy":"validation","validationCode":"if len(b) > 0xFFFF {\n    return errors.New(\"payload exceeds relay frame limit (65535)\")\n}","typeGuard":null,"tryCatchPattern":"if _, err := relay.Write(chunk); err != nil {\n    return fmt.Errorf(\"relay write failed: %w\", err)\n}","preventionTips":["Cap read/copy buffers at 64KB when piping into relay conns","Chunk large payloads before Write","Keep the framing limit consistent across relay implementations"],"tags":["relay","write-limit","framing"],"backgroundTag":"payload-size-limit-exceeded","analyzedSha":"a33fdbf4c98034f4bfeeaea9868909822b9c526d","analyzedAt":"2026-09-02T22:15:54.506Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}