alibaba/open-code-review · error
main_task.messages must not be empty
Error message
main_task.messages must not be empty
What it means
Template.Validate requires the main task conversation to contain at least one message; a Template with no MAIN_TASK messages has nothing to send to the LLM, so Validate returns 'main_task.messages must not be empty'. This is thrown for programmatically built templates or manifests where MAIN_TASK.messages is an empty array or the field is absent.
Source
Thrown at internal/config/template/template.go:323
}
if t.ProjectSummaryTask != nil {
applyLanguage(t.ProjectSummaryTask, instruction)
}
applyLanguage(&t.MemoryCompressionTask, instruction)
}
func (t *Template) Validate() error {
if t.MaxTokens <= 0 {
return fmt.Errorf("max_tokens must be positive")
}
if t.MaxToolRequestTimes <= 0 {
return fmt.Errorf("max_tool_request_times must be positive")
}
if t.MaxReviewRounds < 0 {
return fmt.Errorf("max_review_rounds must not be negative")
}
if len(t.MainTask.Messages) == 0 {
return fmt.Errorf("main_task.messages must not be empty")
}
return nil
}
// Validate checks that a ScanTemplate has the minimum fields populated.
func (t *ScanTemplate) Validate() error {
if t.MaxTokens <= 0 {
return fmt.Errorf("scan: max_tokens must be positive")
}
if t.MaxToolRequestTimes <= 0 {
return fmt.Errorf("scan: max_tool_request_times must be positive")
}
if len(t.MainTask.Messages) == 0 {
return fmt.Errorf("scan: main_task.messages must not be empty")
}
return nil
}
View on GitHub (pinned to 5cf97d0d15)
Solutions
- Add at least one message (typically a system prompt referencing a promptFile) to MAIN_TASK in task_template.json and rebuild
- When constructing Template in Go, populate MainTask.Messages from resolveConversation or literal ChatMessage values before Validate
- Guard any script that generates the manifest to fail if it would emit an empty messages array
- Run the package tests (TestValidate_*) after editing to confirm the manifest still validates
Example fix
// before (task_template.json)
{"MAIN_TASK": {"messages": []}}
// after
{"MAIN_TASK": {"messages": [{"role": "system", "promptFile": "prompts/main_system.md"}]}} Defensive patterns
Strategy: validation
Validate before calling
if len(tpl.MainTask.Messages) == 0 {
return fmt.Errorf("MainTask must have at least one message before Validate")
}
if err := tpl.Validate(); err != nil { return err } Type guard
func hasMainTaskMessages(t *template.Template) bool {
return t != nil && len(t.MainTask.Messages) > 0
} Try / catch
if err := tpl.Validate(); err != nil {
if strings.Contains(err.Error(), "main_task.messages must not be empty") {
return fmt.Errorf("template was built without MAIN_TASK messages; populate MainTask via resolveConversation or LoadDefault")
}
return err
} Prevention
- Prefer LoadDefault/LoadScanDefault over hand-built Template literals
- Fail manifest generators when messages arrays would be empty
- Keep at least one system message in MAIN_TASK when trimming templates
When it happens
Trigger: Calling (*Template).Validate() with len(t.MainTask.Messages) == 0 — e.g. task_template.json with "MAIN_TASK": {"messages": []}, a template literal with MainTask unset, or resolveConversation failing silently upstream is impossible here (it errors), so this is purely an emptiness check.
Common situations: Authoring a custom template manifest and forgetting to add messages; truncating the JSON during editing; constructing a Template in tests/injection code and skipping MainTask; a generation script that emitted an empty messages array.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- invalid config: %w
- max_tokens must be positive
- max_tool_request_times must be positive
- load scan template: %w
- invalid scan template: %w
AI-assisted analysis of alibaba/open-code-review@5cf97d0d15 (2026-09-02).
Data as JSON: /api/errors/c38bd498bdd913dd.
Report an issue: GitHub.