mudler/LocalAI · error
router/score: system_prompt_template: %v
Error message
router/score: system_prompt_template: %v
What it means
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.
Source
Thrown at core/services/routing/router/score.go:212
case "", ScoreNormalizationRaw:
opts.Normalization = ScoreNormalizationRaw
case ScoreNormalizationMean:
// ok
default:
panic(fmt.Sprintf("router/score: unknown score_normalization %q (want %q or %q)",
opts.Normalization, ScoreNormalizationRaw, ScoreNormalizationMean))
}
candidates := make([]string, len(labels))
for i, l := range labels {
candidates[i] = buildCandidate(l, opts.StopToken)
}
systemPrompt, err := renderSystemPrompt(opts.SystemPromptTemplate, policies)
if err != nil {
// Parse-time error here means the operator-supplied template
// is malformed. Config-load validation (ModelConfig.Validate)
// should have caught it earlier; reaching this is either a
// direct programmatic construction or a validation gap.
panic(fmt.Sprintf("router/score: system_prompt_template: %v", err))
}
return &ScoreClassifier{
scorer: scorer,
activationThreshold: opts.ActivationThreshold,
normalization: opts.Normalization,
renderer: opts.PromptRenderer,
systemPrompt: systemPrompt,
labelOrder: labels,
candidates: candidates,
budget: &lazyBudget{
tokenize: opts.TokenCounter,
maxContext: opts.MaxContextTokens,
extras: candidates,
reserve: opts.CompletionReserveTokens,
},
cache: newLabelSetCache(opts.CacheCap),
}
}View on GitHub (pinned to 44413a9d06)
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
Example fix
# before (yaml)
classifier:
type: score
system_prompt_template: "Score the request. {{ label" # unbalanced
# after
classifier:
type: score
system_prompt_template: "Score the request for {{label}}." Defensive patterns
Strategy: validation
Validate before calling
if _, err := renderSystemPrompt(opts.SystemPromptTemplate, policies); err != nil {
return fmt.Errorf("router: bad system_prompt_template: %w", err)
} Type guard
func templateParses(tmpl string, policies []ScorePolicy) bool { _, err := renderSystemPrompt(tmpl, policies); return err == nil } Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- router/rerank: policy has empty label
- router/rerank: policy %q has no description
- router/score: policy has empty label
- router/score: policy %q has no description
- router/rerank: at least one policy is required
AI-assisted analysis of mudler/LocalAI@44413a9d06 (2026-08-15).
Data as JSON: /api/errors/411d9381e33964d1.
Report an issue: GitHub.