XTLS/Xray-core · error

failed to get outbound handler with tag: ${tag}

Error message

failed to get outbound handler with tag: ${tag}

What it means

Raised in the handler's connection dialer when the outbound is configured to dial through another handler identified by tag (e.g. a chained outbound using proxySettings.tag, optionally wrapped in TLS from streamSettings), and no registered outbound handler carries that tag. The lookup fails, the error is logged, and dialing aborts — the fallback is to dial directly only in the success path, which is never reached here.

Source

Thrown at app/proxyman/outbound/handler.go:302

					Tag:    tag,
				})) // add another outbound in session ctx
				opts := pipe.OptionsFromContext(ctx)
				uplinkReader, uplinkWriter := pipe.New(opts...)
				downlinkReader, downlinkWriter := pipe.New(opts...)

				go handler.Dispatch(ctx, &transport.Link{Reader: uplinkReader, Writer: downlinkWriter})
				conn := cnc.NewConnection(cnc.ConnectionInputMulti(uplinkWriter), cnc.ConnectionOutputMulti(downlinkReader))

				if config := tls.ConfigFromStreamSettings(h.streamSettings); config != nil {
					tlsConfig := config.GetTLSConfig(tls.WithDestination(dest))
					conn = tls.Client(conn, tlsConfig)
				}

				return h.getStatCouterConnection(conn), nil
			}

			errors.LogError(ctx, "failed to get outbound handler with tag: ", tag)
			return nil, errors.New("failed to get outbound handler with tag: " + tag)
		}

		if h.senderSettings.Via != nil {
			outbounds := session.OutboundsFromContext(ctx)
			ob := outbounds[len(outbounds)-1]
			h.SetOutboundGateway(ctx, ob)
		}
	}

	conn, err := internet.Dial(ctx, dest, h.streamSettings)
	conn = h.getStatCouterConnection(conn)
	outbounds := session.OutboundsFromContext(ctx)
	if outbounds != nil {
		ob := outbounds[len(outbounds)-1]
		ob.Conn = conn
	} else {
		// for Vision's pre-connect
	}

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Check the exact spelling/case of the tag in proxySettings against the "tag" field of the target outbound in config.
  2. Ensure the referenced outbound is actually defined in the outbounds array (and not removed by a GUI/ template collapse).
  3. Prefer using routing rules/balancers with existing tags instead of manual chaining, or define the tag on both ends consistently.
  4. After fixing, restart and confirm with loglevel info that no 'failed to get outbound handler' lines appear.

Example fix

// before
{ "tag": "chain", "protocol": "freedom",
  "settings": { "domainStrategy": "UseIP" },
  "streamSettings": { "sockopt": { }, "proxySettings": { "tag": "prox" } } }

// after
{ "tag": "chain", "protocol": "freedom",
  "settings": { "domainStrategy": "UseIP" },
  "streamSettings": { "proxySettings": { "tag": "proxy" } } }
// matching an outbound defined as: { "tag": "proxy", "protocol": "vless", ... }
Defensive patterns

Strategy: validation

Validate before calling

// Verify tag exists before dispatch/dial relies on it
ohm := feature.GetOutboundManager(ctx) // app/proxyman/outbound Manager
if h, ok := ohm.GetHandler(chainedTag); !ok || h == nil {
    return fmt.Errorf("config error: chained outbound tag %q undefined", chainedTag)
}

Type guard

func hasOutboundTag(ohm outbound.Manager, tag string) bool {
    h, ok := ohm.GetHandler(tag)
    return ok && h != nil
}

Try / catch

// Fail loudly at config-load time, not per-connection at runtime
for _, ob := range cfg.Outbounds {
    if t := streamProxyTag(ob); t != "" && !definedTags[t] {
        return fmt.Errorf("outbound %q references undefined tag %q", ob.Tag, t)
    }
}

Prevention

When it happens

Trigger: Handler config with proxySettings (or streamSettings-based chaining) whose tag string does not match any handler registered in the outbound manager — for example tag 'proxy' vs registered 'outbound-proxy', a handler removed/renamed, or a tag defined only on the server side. The code path builds an internal pipe connection and dispatches through the resolved handler; resolution failing triggers the error before internet.Dial.

Common situations: Renaming an outbound in config but forgetting to update references in another outbound's proxySettings.tag or in routing balancer rules; typo in the tag; referencing a tag that is created later/dynamically; exporting a template that omits the referenced outbound.

Related errors


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