{"record":{"id":"411d9381e33964d1","repo":"mudler/LocalAI","slug":"router-score-system-prompt-template-v","errorCode":null,"errorMessage":"router/score: system_prompt_template: %v","messagePattern":"router/score: system_prompt_template: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/services/routing/router/score.go","lineNumber":212,"sourceCode":"\tcase \"\", ScoreNormalizationRaw:\n\t\topts.Normalization = ScoreNormalizationRaw\n\tcase ScoreNormalizationMean:\n\t\t// ok\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"router/score: unknown score_normalization %q (want %q or %q)\",\n\t\t\topts.Normalization, ScoreNormalizationRaw, ScoreNormalizationMean))\n\t}\n\tcandidates := make([]string, len(labels))\n\tfor i, l := range labels {\n\t\tcandidates[i] = buildCandidate(l, opts.StopToken)\n\t}\n\tsystemPrompt, err := renderSystemPrompt(opts.SystemPromptTemplate, policies)\n\tif err != nil {\n\t\t// Parse-time error here means the operator-supplied template\n\t\t// is malformed. Config-load validation (ModelConfig.Validate)\n\t\t// should have caught it earlier; reaching this is either a\n\t\t// direct programmatic construction or a validation gap.\n\t\tpanic(fmt.Sprintf(\"router/score: system_prompt_template: %v\", err))\n\t}\n\treturn &ScoreClassifier{\n\t\tscorer:              scorer,\n\t\tactivationThreshold: opts.ActivationThreshold,\n\t\tnormalization:       opts.Normalization,\n\t\trenderer:            opts.PromptRenderer,\n\t\tsystemPrompt:        systemPrompt,\n\t\tlabelOrder:          labels,\n\t\tcandidates:          candidates,\n\t\tbudget: &lazyBudget{\n\t\t\ttokenize:   opts.TokenCounter,\n\t\t\tmaxContext: opts.MaxContextTokens,\n\t\t\textras:     candidates,\n\t\t\treserve:    opts.CompletionReserveTokens,\n\t\t},\n\t\tcache: newLabelSetCache(opts.CacheCap),\n\t}\n}","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/mudler/LocalAI/blob/44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26/core/services/routing/router/score.go#L194-L230","documentation":"Construction-time panic in NewScoreClassifier: renderSystemPrompt failed to parse/render the operator-supplied system_prompt_template. The comment notes ModelConfig.Validate should catch malformed templates at config-load time, so reaching this panic means either direct programmatic construction or a validation gap between config loading and classifier construction.","triggerScenarios":"Setting system_prompt_template in the router score classifier config to a template with syntax errors (unbalanced delimiters, bad placeholders); passing ScoreClassifierOptions.SystemPromptTemplate directly to NewScoreClassifier without going through ModelConfig.Validate.","commonSituations":"A system_prompt_template with unbalanced {{ }} delimiters or invalid template syntax; template valid at validation time but policies changed before construction; programmatic callers passing an unvalidated template; version skew where the template engine grammar changed.","solutions":["Fix the template syntax (balance delimiters/placeholders) in the router classifier config","Test the template in isolation with the same policies data","If constructing programmatically, run the same validation ModelConfig.Validate uses before calling NewScoreClassifier","Report/fix the validation gap if config-loaded templates reach this panic"],"exampleFix":"# before (yaml)\nclassifier:\n  type: score\n  system_prompt_template: \"Score the request. {{ label\"  # unbalanced\n# after\nclassifier:\n  type: score\n  system_prompt_template: \"Score the request for {{label}}.\"","handlingStrategy":"validation","validationCode":"if _, err := renderSystemPrompt(opts.SystemPromptTemplate, policies); err != nil {\n    return fmt.Errorf(\"router: bad system_prompt_template: %w\", err)\n}","typeGuard":"func templateParses(tmpl string, policies []ScorePolicy) bool { _, err := renderSystemPrompt(tmpl, policies); return err == nil }","tryCatchPattern":null,"preventionTips":["Dry-run templates with representative policies during config validation","Keep ModelConfig.Validate and the constructor's expectations in sync when editing templates","Add a unit test that constructs the classifier from every shipped example config"],"tags":["router","config","template","validation","panic"],"backgroundTag":null,"analyzedSha":"44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26","analyzedAt":"2026-08-15T10:13:50.291Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}