{"record":{"id":"f2045b8b26fda46b","repo":"mudler/LocalAI","slug":"router-rerank-policy-has-empty-label","errorCode":null,"errorMessage":"router/rerank: policy has empty label","messagePattern":"router/rerank: policy has empty label","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/services/routing/router/rerank.go","lineNumber":48,"sourceCode":"\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 {\n\t\tlabels[i] = p.Label\n\t\tdocs[i] = p.Description\n\t}\n\treturn &RerankClassifier{\n\t\treranker:            reranker,\n\t\tactivationThreshold: activationThreshold,\n\t\tlabels:              labels,","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/mudler/LocalAI/blob/44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26/core/services/routing/router/rerank.go#L30-L66","documentation":"Construction-time panic in NewRerankClassifier: one of the supplied ScorePolicy entries has an empty Label. Labels are both the routing output value and the reranker candidate text anchor, so an empty label is meaningless downstream and is rejected eagerly.","triggerScenarios":"A policies list entry missing its label key, or label: \"\" in YAML; programmatically appending a zero-value ScorePolicy{}; whitespace-only labels after trimming in config.","commonSituations":"YAML typo (labels vs label, or the field named differently); copy-pasted policy block with the label line accidentally removed; config schema that allows label to be optional.","solutions":["Find the policy without a label in the router config and give it a non-empty label","Check for singular/plural or misnamed keys (label, not labels/name)","Add config-time validation to report which policy index is malformed before the panic"],"exampleFix":"# before (yaml)\npolicies:\n  - description: \"programming questions\"\n# after\npolicies:\n  - label: code\n    description: \"programming questions\"","handlingStrategy":"validation","validationCode":"for i, p := range policies {\n    if strings.TrimSpace(p.Label) == \"\" {\n        return fmt.Errorf(\"policy %d: empty label\", i)\n    }\n}","typeGuard":"func validLabels(ps []ScorePolicy) bool { for _, p := range ps { if p.Label == \"\" { return false } }; return true }","tryCatchPattern":null,"preventionTips":["Lint router policies for label+description presence","Use strict YAML schemas that reject missing keys","Generate policy lists from tested templates"],"tags":["router","config","validation","panic"],"backgroundTag":null,"analyzedSha":"44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26","analyzedAt":"2026-08-15T10:13:50.291Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}