{"record":{"id":"e5fedab5f0c35645","repo":"XTLS/Xray-core","slug":"failed-to-get-dispatcher-for-geodata-downloader","errorCode":null,"errorMessage":"failed to get dispatcher for geodata downloader","messagePattern":"failed to get dispatcher for geodata downloader","errorType":"exception","errorClass":"errors.Error","httpStatus":null,"severity":"error","filePath":"app/geodata/geodata.go","lineNumber":38,"sourceCode":"\tmu      sync.Mutex\n\trunning bool\n}\n\nfunc New(ctx context.Context, config *Config) (*Instance, error) {\n\tif config.Cron == \"\" {\n\t\treturn &Instance{}, nil\n\t}\n\n\tg := &Instance{\n\t\tassets: config.Assets,\n\t}\n\n\tif len(g.assets) > 0 {\n\t\tvar dispatcher routing.Dispatcher\n\t\tif err := core.RequireFeatures(ctx, func(d routing.Dispatcher) {\n\t\t\tdispatcher = d\n\t\t}); err != nil {\n\t\t\treturn nil, errors.New(\"failed to get dispatcher for geodata downloader\").Base(err)\n\t\t}\n\t\tg.downloader = newDownloader(ctx, dispatcher, config.Outbound)\n\t}\n\n\tg.tasker = cron.New(\n\t\tcron.WithChain(cron.SkipIfStillRunning(cron.DiscardLogger)),\n\t\tcron.WithLogger(cron.DiscardLogger),\n\t)\n\tif _, err := g.tasker.AddFunc(config.Cron, g.execute); err != nil {\n\t\treturn nil, errors.New(\"invalid geodata cron\").Base(err)\n\t}\n\terrors.LogInfo(ctx, \"scheduled geodata reload with cron: \", config.Cron)\n\n\treturn g, nil\n}\n\nfunc (g *Instance) execute() {\n\tvar err error","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/app/geodata/geodata.go#L20-L56","documentation":"Thrown during geodata Instance creation when core.RequireFeatures cannot resolve a routing.Dispatcher on the instance. The downloader needs the dispatcher to dial through a tagged outbound, so without it the component cannot start; the original RequireFeatures error is chained.","triggerScenarios":"Config declares geodata assets (len(config.Assets) > 0) but the core instance being built has no routing/dispatcher feature registered yet — e.g. feature registration order is wrong, or geodata is initialized in a stripped-down instance that lacks app/router.","commonSituations":"Embedding Xray-core as a library and calling New() before registering router features; custom builds that omit the router app; startup-order regressions after a version upgrade.","solutions":["Ensure app/router (which provides routing.Dispatcher) is registered in the instance features before geodata is created","Run via the standard xray binary/config pipeline, which registers features in the correct order","If geodata auto-update is not needed, clear the geodata assets list so the dispatcher requirement is skipped"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// When embedding Xray-core, register the router app before creating geodata:\n// (order matters — RequireFeatures resolves lazily but the feature must be\n// registered with the instance)\ninstance := core.New(config) // ensure config includes app/router\n// then start geodata; dispatcher feature will resolve","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use the standard xray startup path which registers all required features","Do not strip the router app from builds that enable geodata auto-update","Omit the geodata assets list when running a dispatcher-less instance"],"tags":["geodata","feature-registration","dispatcher","startup"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}