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

  1. Fix the template syntax (balance delimiters/placeholders) in the router classifier config
  2. Test the template in isolation with the same policies data
  3. If constructing programmatically, run the same validation ModelConfig.Validate uses before calling NewScoreClassifier
  4. 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

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


AI-assisted analysis of mudler/LocalAI@44413a9d06 (2026-08-15). Data as JSON: /api/errors/411d9381e33964d1. Report an issue: GitHub.