mudler/LocalAI · error

router/score: scorer is required (configure router.classifie

Error message

router/score: scorer is required (configure router.classifier_model)

What it means

Construction-time panic in NewScoreClassifier: the scorer backend handle is nil. The scorer (configured via router.classifier_model) is the model whose logprobs the classifier reads to score each label candidate; nil means no scoring backend exists, so the classifier cannot work.

Source

Thrown at core/services/routing/router/score.go:170

	// common prefix of two synthetic probes) and sent with each Score
	// call as a state-reuse boundary hint — on backends whose models
	// cannot rewind state (hybrid/recurrent), a snapshot at this
	// boundary is what keeps repeat scoring at probe-size cost instead
	// of a full option-list re-prefill.
	stablePrefixOnce sync.Once
	stablePrefix     string
}

// NewScoreClassifier panics on caller errors at construction (empty
// policies, missing description, nil scorer) — same rationale as the
// other classifiers. See ScoreClassifierOptions for the optional
// knobs and their zero-value defaults.
func NewScoreClassifier(policies []ScorePolicy, scorer backend.Scorer, opts ScoreClassifierOptions) *ScoreClassifier {
	if len(policies) == 0 {
		panic("router/score: at least one policy is required")
	}
	if scorer == nil {
		panic("router/score: scorer is required (configure router.classifier_model)")
	}
	for _, p := range policies {
		if p.Label == "" {
			panic("router/score: policy has empty label")
		}
		if p.Description == "" {
			panic(fmt.Sprintf("router/score: policy %q has no description", p.Label))
		}
	}
	labels := make([]string, 0, len(policies))
	for _, p := range policies {
		labels = append(labels, p.Label)
	}
	if opts.ActivationThreshold <= 0 {
		opts.ActivationThreshold = defaultActivationThreshold
	}
	if opts.StopToken == "" {
		opts.StopToken = defaultStopToken

View on GitHub (pinned to 44413a9d06)

Solutions

  1. Set router.classifier_model to an installed, score-capable model
  2. Confirm the model loads (check startup logs / model list)
  3. Ensure the chosen backend implements backend.Scorer (exposes token logprobs)
  4. If constructing programmatically, resolve the scorer and fail with a clear error before calling the constructor

Example fix

# before (yaml)
router:
  classifier:
    type: score
    policies: [...]
# after
router:
  classifier_model: classifier-model
  classifier:
    type: score
    policies: [...]
Defensive patterns

Strategy: validation

Validate before calling

scorer, err := resolveModel(cfg.Router.ClassifierModel)
if err != nil || scorer == nil {
    return fmt.Errorf("router: classifier_model %q not loaded", cfg.Router.ClassifierModel)
}

Type guard

func implementsScorer(m backend.Backend) bool { _, ok := m.(backend.Scorer); return ok }

Prevention

When it happens

Trigger: router.classifier_model unset or pointing at a model that failed to load/resolution returned nil; calling NewScoreClassifier(policies, nil, opts) directly; model registry not yet populated when the router is constructed.

Common situations: Enabling the score router without a classifier model installed; classifier_model typo; referencing a chat model without logprob support as the scorer; startup ordering where the router builds before backends register.

Related errors


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