{"record":{"id":"4f8cd5054c0e4a3f","repo":"XTLS/Xray-core","slug":"cannot-get-depended-features-4f8cd5","errorCode":null,"errorMessage":"Cannot get depended features","messagePattern":"Cannot get depended features","errorType":"exception","errorClass":"errors.Error","httpStatus":null,"severity":"error","filePath":"app/observatory/observer.go","lineNumber":238,"sourceCode":"\nfunc (o *Observer) findStatusLocationLockHolderOnly(outbound string) int {\n\tfor i, v := range o.status {\n\t\tif v.OutboundTag == outbound {\n\t\t\treturn i\n\t\t}\n\t}\n\treturn -1\n}\n\nfunc New(ctx context.Context, config *Config) (*Observer, error) {\n\tvar outboundManager outbound.Manager\n\tvar dispatcher routing.Dispatcher\n\terr := core.RequireFeatures(ctx, func(om outbound.Manager, rd routing.Dispatcher) {\n\t\toutboundManager = om\n\t\tdispatcher = rd\n\t})\n\tif err != nil {\n\t\treturn nil, errors.New(\"Cannot get depended features\").Base(err)\n\t}\n\treturn &Observer{\n\t\tconfig:     config,\n\t\tctx:        ctx,\n\t\tohm:        outboundManager,\n\t\tdispatcher: dispatcher,\n\t}, nil\n}\n\nfunc init() {\n\tcommon.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {\n\t\treturn New(ctx, config.(*Config))\n\t}))\n}\n","sourceCodeStart":220,"sourceCodeEnd":253,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/app/observatory/observer.go#L220-L253","documentation":"Returned by New() for the classic observatory (app/observatory/observer.go:238) when core.RequireFeatures cannot resolve outbound.Manager and routing.Dispatcher from the instance context. The observer dispatches its probes through the routing dispatcher and enumerates outbounds through the manager, so without both features it cannot start.","triggerScenarios":"Constructing an Observatory on a core instance that lacks the proxyman app or where feature registration did not complete before the observatory initializes. In JSON-driven configs proxyman is always present, so this is essentially a library-embedding or app-ordering problem.","commonSituations":"Custom xray-core builds that assemble core.Config.App manually and forget proxyman; or third-party tools that lazily start apps and race the observatory's RequireFeatures.","solutions":["Include the proxyman app in the instance's app list before creating the observatory.","Check the Base error to see which required feature was missing.","If configuring via JSON, ensure the observatory block sits at the top level of the same config as outbounds."],"exampleFix":"// before\ncfg.App = append(cfg.App, serial.ToTypedMessage(&observatory.Config{ ... }))\n\n// after\ncfg.App = append(cfg.App,\n  serial.ToTypedMessage(&proxyman.Config{}),\n  serial.ToTypedMessage(&observatory.Config{ ... }),\n)","handlingStrategy":"validation","validationCode":"// verify required features before constructing the observer\nif _, ok := core.GetFeature(ctx, outbound.ManagerType()).(outbound.Manager); !ok {\n    return errors.New(\"outbound manager feature missing\")\n}","typeGuard":null,"tryCatchPattern":"obs, err := observatory.New(ctx, cfg)\nif err != nil {\n    return fmt.Errorf(\"observatory unavailable on this instance: %w\", err)\n}","preventionTips":["Register proxyman in embedded instances before observatory apps.","Fail fast at startup when feature resolution fails instead of disabling observation silently."],"tags":["go","xray","dependency-injection","configuration"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}