{"record":{"id":"a7ec814e49b2434b","repo":"mudler/LocalAI","slug":"router-rerank-at-least-one-policy-is-required","errorCode":null,"errorMessage":"router/rerank: at least one policy is required","messagePattern":"router/rerank: at least one policy is required","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/services/routing/router/rerank.go","lineNumber":41,"sourceCode":"\tlabels    []string\n\tdocuments []string\n\tcache     *labelSetCache\n\n\t// budget trims the query to the reranker model's context minus the\n\t// longest policy description (paired with the query per rerank call);\n\t// nil reranks Probe.Prompt as built by the caller.\n\tbudget *lazyBudget\n}\n\n// defaultRerankActivationThreshold is the relevance floor a label\n// must clear to be considered active. Reranker scores live in [0, 1]\n// for cross-encoder / ColBERT heads; 0.5 picks \"more positive than\n// not on this label.\"\nconst defaultRerankActivationThreshold = 0.5\n\nfunc NewRerankClassifier(policies []ScorePolicy, reranker backend.Reranker, cacheCap int, activationThreshold float64) *RerankClassifier {\n\tif len(policies) == 0 {\n\t\tpanic(\"router/rerank: at least one policy is required\")\n\t}\n\tif reranker == nil {\n\t\tpanic(\"router/rerank: reranker is required (configure router.classifier_model)\")\n\t}\n\tfor _, p := range policies {\n\t\tif p.Label == \"\" {\n\t\t\tpanic(\"router/rerank: policy has empty label\")\n\t\t}\n\t\tif p.Description == \"\" {\n\t\t\tpanic(fmt.Sprintf(\"router/rerank: policy %q has no description\", p.Label))\n\t\t}\n\t}\n\tif activationThreshold <= 0 {\n\t\tactivationThreshold = defaultRerankActivationThreshold\n\t}\n\tlabels := make([]string, len(policies))\n\tdocs := make([]string, len(policies))\n\tfor i, p := range policies {","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/mudler/LocalAI/blob/44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26/core/services/routing/router/rerank.go#L23-L59","documentation":"Construction-time panic in the routing rerank classifier: NewRerankClassifier was called with an empty policies slice. Policies (label + description pairs) are what get scored against the reranker, so zero policies leaves the classifier with nothing to classify — a programming/config invariant, not a runtime data condition.","triggerScenarios":"Router config enables a rerank-based classifier but defines no policies under it; programmatically calling NewRerankClassifier(nil, ...) or with an empty slice; a config loader that silently drops malformed policy entries and passes the emptied slice through.","commonSituations":"YAML router section with classifier enabled but an empty/omitted policies list; indentation mistakes that detach policies from the classifier block; tests constructing the classifier with no policies.","solutions":["Add at least one policy (label + description) to the router's classifier config","Check YAML indentation so policies are nested under the classifier section","If constructing in Go, guard the call site: only build the classifier when len(policies) > 0","Validate config at load time so the error surfaces as a config error rather than a panic"],"exampleFix":"# before (yaml)\nrouter:\n  classifier:\n    type: rerank\n    policies: []\n# after\nrouter:\n  classifier:\n    type: rerank\n    policies:\n      - label: code\n        description: \"requests about programming\"","handlingStrategy":"validation","validationCode":"if len(cfg.Router.Classifier.Policies) == 0 {\n    return fmt.Errorf(\"router: classifier requires at least one policy\")\n}","typeGuard":"func hasPolicies(p []ScorePolicy) bool { return len(p) > 0 }","tryCatchPattern":"// panics are construction-time; recover only at plugin boundaries\ndefer func() { if r := recover(); r != nil { log.Printf(\"router init failed: %v\", r) } }()","preventionTips":["Validate router config sections at load time with descriptive errors","Write config examples that always include one policy","Unit-test config parsing against the panic preconditions"],"tags":["router","config","panic","construction"],"backgroundTag":null,"analyzedSha":"44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26","analyzedAt":"2026-08-15T10:13:50.291Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}