XTLS/Xray-core · error

failed to read metadata

Error message

failed to read metadata

What it means

ServerWorker.handleFrame could not unmarshal a frame header: FrameMetadata.Unmarshal failed before any status dispatch. This is the umbrella error for all frame-metadata parse failures (target/source/local address errors, insufficient buffer, bad length prefix), and it terminates the mux connection's read loop.

Source

Thrown at common/mux/server.go:340

	return err
}

func (w *ServerWorker) handleStatusEnd(meta *FrameMetadata, reader *buf.BufferedReader) error {
	if s, found := w.sessionManager.Get(meta.SessionID); found {
		s.Close(false)
	}
	if meta.Option.Has(OptionData) {
		return buf.Copy(NewStreamReader(reader), buf.Discard)
	}
	return nil
}

func (w *ServerWorker) handleFrame(ctx context.Context, reader *buf.BufferedReader) error {
	var meta FrameMetadata
	err := meta.Unmarshal(reader, session.IsReverseMuxFromContext(ctx))
	if err != nil {
		return errors.New("failed to read metadata").Base(err)
	}

	switch meta.SessionStatus {
	case SessionStatusKeepAlive:
		err = w.handleStatusKeepAlive(&meta, reader)
	case SessionStatusEnd:
		err = w.handleStatusEnd(&meta, reader)
	case SessionStatusNew:
		err = w.handleStatusNew(session.ContextWithIsReverseMux(ctx, false), &meta, reader)
	case SessionStatusKeep:
		err = w.handleStatusKeep(&meta, reader)
	default:
		status := meta.SessionStatus
		return errors.New("unknown status: ", status).AtError()
	}

	if err != nil {
		return errors.New("failed to process data").Base(err)

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Look at the Base() error to see which field failed (target address vs source/local vs buffer length) and follow that specific cause.
  2. Confirm both endpoints run the same Xray-core version.
  3. Verify the transport chain (TLS/Reality settings identical on both ends) so the mux layer receives the intended plaintext stream.
  4. Disable mux to confirm the underlying proxy path works, then re-enable and retest.
Defensive patterns

Strategy: try-catch

Try / catch

err := meta.Unmarshal(reader, rev)
if err != nil {
    // inspect chain: errors.New("failed to read metadata").Base(err)
    cause := err
    for errors.Unwrap(cause) != nil { cause = errors.Unwrap(cause) }
    log.Warn("mux metadata failed, root cause: ", cause)
    return err // connection must close
}

Prevention

When it happens

Trigger: The first 2-byte length prefix plus payload do not decode as FrameMetadata: stream desync, non-mux bytes fed to the mux server, truncation, or version-incompatible metadata layout.

Common situations: Pointing a mux-enabled client at a server that terminates TLS and forwards plain bytes elsewhere, transport-level corruption, or downgrade/mismatch between client/server versions.

Related errors


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