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
- Ensure mux is enabled on both ends of the tunnel (client outbound and server inbound handling).
- Disable mux on the outbound to confirm the underlying proxy works; re-enable once verified.
- 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
- Enable mux only where the server inbound is known to support it (same core family).
- Pin compatible client/server versions; test mux handshake after each upgrade.
- Treat any metalen failure as fatal for the connection — never reuse the stream.
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
- insufficient buffer:
- failed to parse address and port
- unknown network type:
- packet size too large:
- failed to read metadata
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/574589e587edc0b9.
Report an issue: GitHub.