XTLS/Xray-core · error · errors.Error

Cannot get depended features

Error message

Cannot get depended features

What it means

Returned by New() for the burst observatory (app/observatory/burst/burstobserver.go:100) when core.RequireFeatures fails to resolve the outbound.Manager and routing.Dispatcher features from the instance context. The burst observer needs the dispatcher to send probe connections and the outbound manager to enumerate/select outbounds; if either feature is not registered in the core instance, the observer cannot be constructed.

Source

Thrown at app/observatory/burst/burstobserver.go:100

}

func (o *Observer) Close() error {
	if o.finished != nil {
		o.hp.StopScheduler()
		return o.finished.Close()
	}
	return nil
}

func New(ctx context.Context, config *Config) (*Observer, error) {
	var outboundManager outbound.Manager
	var dispatcher routing.Dispatcher
	err := core.RequireFeatures(ctx, func(om outbound.Manager, rd routing.Dispatcher) {
		outboundManager = om
		dispatcher = rd
	})
	if err != nil {
		return nil, errors.New("Cannot get depended features").Base(err)
	}
	hp := NewHealthPing(ctx, dispatcher, config.PingConfig)
	return &Observer{
		config: config,
		ctx:    ctx,
		ohm:    outboundManager,
		hp:     hp,
	}, nil
}

func init() {
	common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
		return New(ctx, config.(*Config))
	}))
}

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Ensure the core instance registers the proxyman app (app/proxyman/commander style setup) so outbound.Manager and routing.Dispatcher exist — in JSON configs this is automatic.
  2. If embedding programmatically, append app/proxyman.Manager to core.Config.App before core.New().
  3. Check the returned cause (err) via Base() — it usually says which feature type was missing.
  4. Verify the burst observatory config block is inside the same instance as the outbounds it observes.

Example fix

// before
cfg := &core.Config{App: []serial.Message{&burst.Config{ ... }}}
inst, err := core.New(cfg)

// after — include proxyman so required features resolve
cfg := &core.Config{App: []serial.Message{
  &proxyman.Config{},
  &burst.Config{ ... },
}}
inst, err := core.New(cfg)
Defensive patterns

Strategy: validation

Validate before calling

// when embedding: ensure proxyman is registered before burst observatory
hasProxyman := false
for _, m := range cfg.App {
    if strings.Contains(m.TypeUrl, "app.proxyman") { hasProxyman = true }
}
if !hasProxyman && usesBurstObservatory(cfg) {
    return fmt.Errorf("burst observatory requires proxyman features")
}

Try / catch

if _, err := burst.New(ctx, bcfg); err != nil {
    return fmt.Errorf("burst observer init failed: %w", err) // inspect Base for missing feature
}

Prevention

When it happens

Trigger: Creating a burst Observatory whose inbound/outbound dependencies are unsatisfiable — typically when the app is registered on a core.Instance built without the proxyman app (which provides both outbound.Manager and routing.Dispatcher), or when feature resolution order fails because dependencies are started in the wrong phase.

Common situations: Embedding xray-core as a library and building a minimal core.Instance with an app list that includes burst observatory but omits proxyman; or a config where the observatory is loaded in an unusual feature-registration order. Rarely seen in normal full JSON configs because proxyman is always present.

Related errors


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