egametang/ET · error · Exception

send packet too large: {stream.Length} {stream.Position}

Error message

send packet too large: {stream.Length} {stream.Position}

What it means

TChannel.Send enforces an upper bound (ushort.MaxValue*16 ~= 1 MiB) on inner-channel messages by comparing stream.Length - stream.Position. Larger inner messages are rejected because the 4-byte size header / memory model cannot safely carry them.

Source

Thrown at Packages/cn.etetet.core/Scripts/Core/Share/Network/TChannel.cs:107

			this.outArgs = null;
			this.socket = null;
		}

		public void Send(MemoryBuffer stream)
		{
			if (this.IsDisposed)
			{
				throw new Exception("TChannel已经被Dispose, 不能发送消息");
			}
			
			switch (this.Service.ServiceType)
			{
				case ServiceType.Inner:
				{
					int messageSize = (int) (stream.Length - stream.Position);
					if (messageSize > ushort.MaxValue * 16)
					{
						throw new Exception($"send packet too large: {stream.Length} {stream.Position}");
					}

					this.sendCache.WriteTo(0, messageSize);
					this.sendBuffer.Write(this.sendCache, 0, PacketParser.InnerPacketSizeLength);
					break;
				}
				case ServiceType.Outer:
				{
					ushort messageSize = (ushort) (stream.Length - stream.Position);
					this.sendCache.WriteTo(0, messageSize);
					this.sendBuffer.Write(this.sendCache, 0, PacketParser.OuterPacketSizeLength);
					break;
				}
			}
			
			this.sendBuffer.Write(stream.GetBuffer(), (int)stream.Position, (int)(stream.Length - stream.Position));
			if (!this.isSending)
			{

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Chunk large payloads into multiple messages under the limit.
  2. Move bulk data out of band (shared store, file transfer) instead of one RPC.
  3. Compress or trim the payload.

Example fix

// before
innerChannel.Send(hugeMemoryBuffer);
// after
foreach (var chunk in Split(hugeMemoryBuffer, 512 * 1024))
    innerChannel.Send(chunk);
Defensive patterns

Strategy: validation

Validate before calling

const int InnerMax = ushort.MaxValue * 16;
int msgSize = (int)(stream.Length - stream.Position);
if (msgSize > InnerMax) throw new InvalidOperationException($"message too large: {msgSize}");
channel.Send(stream);

Type guard

static bool FitsInnerMessage(long length, long position) => length - position <= ushort.MaxValue * 16;

Try / catch

null

Prevention

When it happens

Trigger: Serializing a very large object (big snapshot, blob, list) and sending it on an inner (server-to-server) channel in a single message.

Common situations: Full-state sync, large config push, or a log/binary blob sent as one message.

Related errors


AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13). Data as JSON: /api/errors/c7ef33031133443b. Report an issue: GitHub.