alibaba/open-code-review · error

scan template MAIN_TASK is missing or empty

Error message

scan template MAIN_TASK is missing or empty

What it means

Agent.Run refuses to start the full-scan pipeline when the scan template's MAIN_TASK prompt has no messages. The MAIN_TASK template drives the per-file review loop, so an empty template means the scan cannot produce meaningful requests; the error fails fast before any enumeration or LLM calls.

Source

Thrown at internal/scan/agent.go:304

}

func scanItemFingerprint(it model.ScanItem) string {
	sum := sha256.Sum256([]byte(session.ReviewModeFullScan + "\x00" + it.Path + "\x00" + it.Content))
	return fmt.Sprintf("%x", sum)
}

func resumedFromSession(resume *session.ResumeState) string {
	if resume == nil {
		return ""
	}
	return resume.SessionID
}

// Run executes the full-scan pipeline: enumerate → filter → token-filter →
// dispatch one subtask per file → collect comments.
func (a *Agent) Run(ctx context.Context) ([]model.LlmComment, error) {
	if len(a.args.Template.MainTask.Messages) == 0 {
		return nil, fmt.Errorf("scan template MAIN_TASK is missing or empty")
	}

	// Base prompt-cache affinity key for any LLM request in this run that a
	// task doesn't re-scope. Each task conversation (plan, per-file main
	// loop, dedup, summary) refines it with llm.SessionTaskKey where it
	// starts, so affinity keys stay per-conversation — the granularity
	// provider prompt caches actually reuse prefixes at.
	ctx = llm.ContextWithSessionKey(ctx, a.SessionID())

	ctx, scanSpan := telemetry.StartSpan(ctx, "scan.enumerate")
	provider := NewProvider(a.args.RepoDir, a.args.Paths, a.args.GitRunner, a.args.MaxFileSizeBytes)
	items, err := provider.Enumerate(ctx)
	if err != nil {
		scanSpan.End()
		return nil, fmt.Errorf("enumerate files: %w", err)
	}
	telemetry.SetAttr(scanSpan, "files.enumerated", len(items))
	scanSpan.End()

View on GitHub (pinned to 5cf97d0d15)

Solutions

  1. Provide a template whose MAIN_TASK section defines at least one message, or drop the custom template override to use the built-in default
  2. Check the template key spelling — it must be MAIN_TASK (uppercase) with a non-empty messages list
  3. Regenerate/refresh a custom template that was authored against an older OCR version

Example fix

# before (custom template)
[PLAN_TASK]
messages = [...]
# after — add the required section
[MAIN_TASK]
messages = [{ role = "user", content = "Review this file: {{.Content}}" }]
Defensive patterns

Strategy: validation

Validate before calling

// validate the template before running the scan
if len(args.Template.MainTask.Messages) == 0 {
    return fmt.Errorf("custom template must define a non-empty MAIN_TASK section")
}

Try / catch

comments, err := agent.Run(ctx)
if err != nil && strings.Contains(err.Error(), "MAIN_TASK is missing or empty") {
    // fall back to the built-in template or fix the custom template file
}

Prevention

When it happens

Trigger: Running a scan where the resolved scan template (built-in or custom via template config) has an empty or missing MAIN_TASK section — e.g. a custom template file defining only other task keys, or a template path pointing at the wrong file.

Common situations: Pointing --template/custom template config at a file that defines PLAN_TASK/DEDUP_TASK but omits MAIN_TASK; an older template format after an OCR upgrade renamed the key; an empty template file created by mistake.

Related errors


AI-assisted analysis of alibaba/open-code-review@5cf97d0d15 (2026-09-02). Data as JSON: /api/errors/09d51cff704d799f. Report an issue: GitHub.