XTLS/Xray-core · critical

invalid metalen

Error message

invalid metalen 

What it means

FrameMetadata.Unmarshal reads a uint16 meta length from the mux stream and rejects anything over 512 bytes — well-formed mux frame metadata is always far smaller. A larger value means the stream is desynchronized or the peer is speaking a different protocol, so parsing aborts before allocating the buffer.

Source

Thrown at common/mux/frame.go:120

		}
	} else if b.UDP != nil {
		b.WriteByte(byte(TargetNetworkUDP))
		addrParser.WriteAddressPort(b, b.UDP.Address, b.UDP.Port)
	}

	len1 := b.Len()
	binary.BigEndian.PutUint16(lenBytes, uint16(len1-len0))
	return nil
}

// Unmarshal reads FrameMetadata from the given reader.
func (f *FrameMetadata) Unmarshal(reader io.Reader, readSourceAndLocal bool) error {
	metaLen, err := serial.ReadUint16(reader)
	if err != nil {
		return err
	}
	if metaLen > 512 {
		return errors.New("invalid metalen ", metaLen).AtError()
	}

	b := buf.New()
	defer b.Release()

	if _, err := b.ReadFullFrom(reader, int32(metaLen)); err != nil {
		return err
	}
	return f.UnmarshalFromBuffer(b, readSourceAndLocal)
}

// UnmarshalFromBuffer reads a FrameMetadata from the given buffer.
// Visible for testing only.
func (f *FrameMetadata) UnmarshalFromBuffer(b *buf.Buffer, readSourceAndLocal bool) error {
	if b.Len() < 4 {
		return errors.New("insufficient buffer: ", b.Len())
	}

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Ensure mux is enabled on both ends of the tunnel (client outbound and server inbound handling).
  2. Disable mux on the outbound to confirm the underlying proxy works; re-enable once verified.
  3. Align client/server Xray versions to avoid frame format differences.

Example fix

// before
outbound: { "mux": {"enabled": true}, "protocol": "vless", ... } // server lacks mux support

// after
outbound: { "mux": {"enabled": false}, "protocol": "vless", ... }
Defensive patterns

Strategy: try-catch

Try / catch

if err := frame.Unmarshal(reader, false); err != nil {
    if strings.Contains(err.Error(), "invalid metalen") {
        return errors.New("mux stream desynchronized: peer likely not mux-capable").Base(err)
    }
    return err
}

Prevention

When it happens

Trigger: Connecting a mux-enabled outbound to a server that does not support mux (or vice versa), causing arbitrary bytes to be read as a frame header; stream corruption after a partial write; version mismatch in frame format.

Common situations: See trigger scenarios.

Related errors


AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15). Data as JSON: /api/errors/574589e587edc0b9. Report an issue: GitHub.