{"record":{"id":"98aa4bf889aa6bb0","repo":"XTLS/Xray-core","slug":"not-a-strategyleastloadconfig","errorCode":null,"errorMessage":"not a StrategyLeastLoadConfig","messagePattern":"not a StrategyLeastLoadConfig","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/router/config.go","lineNumber":148,"sourceCode":"\t\t\tstrategy:    &LeastPingStrategy{},\n\t\t\tfallbackTag: br.FallbackTag,\n\t\t\tohm:         ohm,\n\t\t}, nil\n\tcase \"roundrobin\":\n\t\treturn &Balancer{\n\t\t\tselectors:   br.OutboundSelector,\n\t\t\tstrategy:    &RoundRobinStrategy{FallbackTag: br.FallbackTag},\n\t\t\tfallbackTag: br.FallbackTag,\n\t\t\tohm:         ohm,\n\t\t}, nil\n\tcase \"leastload\":\n\t\ti, err := br.StrategySettings.GetInstance()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\ts, ok := i.(*StrategyLeastLoadConfig)\n\t\tif !ok {\n\t\t\treturn nil, errors.New(\"not a StrategyLeastLoadConfig\").AtError()\n\t\t}\n\t\tleastLoadStrategy := NewLeastLoadStrategy(s)\n\t\treturn &Balancer{\n\t\t\tselectors:   br.OutboundSelector,\n\t\t\tohm:         ohm,\n\t\t\tfallbackTag: br.FallbackTag,\n\t\t\tstrategy:    leastLoadStrategy,\n\t\t}, nil\n\tcase \"random\":\n\t\tfallthrough\n\tcase \"\":\n\t\treturn &Balancer{\n\t\t\tselectors:   br.OutboundSelector,\n\t\t\tohm:         ohm,\n\t\t\tfallbackTag: br.FallbackTag,\n\t\t\tstrategy:    &RandomStrategy{FallbackTag: br.FallbackTag},\n\t\t}, nil\n\tdefault:","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/app/router/config.go#L130-L166","documentation":"For a 'leastload' balancing rule, StrategySettings must decode to *StrategyLeastLoadConfig. If the settings message is absent-but-typed differently or the embedded instance is another config type, the assertion fails and the balancer build aborts.","triggerScenarios":"Declaring strategy 'leastload' with a strategySettings block whose serialized type is not StrategyLeastLoadConfig (e.g. pasted leastping settings or a random strategy object).","commonSituations":"Copying strategy blocks between rules of different strategy types; JSON configs hand-migrated between versions where settings type names changed.","solutions":["Use the correct settings type for leastload: {\"type\": \"leastload\", \"settings\": {...}} via StrategyLeastLoadConfig fields (costs, baselines, expected status counts)","Remove strategySettings entirely to use defaults if customization is not needed","Regenerate the config with a current schema-aware tool"],"exampleFix":"// before\n\"strategy\": {\n  \"type\": \"leastload\",\n  \"settings\": { \"type\": \"pingconfig\" } // wrong settings type\n}\n\n// after\n\"strategy\": {\n  \"type\": \"leastload\"\n} // defaults, or supply leastload-specific settings","handlingStrategy":"validation","validationCode":"if strings.EqualFold(br.Strategy, \"leastload\") && br.StrategySettings != nil {\n    i, _ := br.StrategySettings.GetInstance()\n    if _, ok := i.(*router.StrategyLeastLoadConfig); !ok {\n        return fmt.Errorf(\"strategySettings must be StrategyLeastLoadConfig for leastload\")\n    }\n}","typeGuard":"func isLeastLoadConfig(i interface{}) bool {\n    _, ok := i.(*router.StrategyLeastLoadConfig)\n    return ok\n}","tryCatchPattern":null,"preventionTips":["Do not copy settings blocks between different strategy types","Omit strategySettings to use defaults unless tuning leastload","After editing strategy config, run xray run -test (config check) before deploying"],"tags":["routing","balancer","configuration","type-mismatch"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}