{"record":{"id":"6880e8e5bbd8ff35","repo":"alibaba/open-code-review","slug":"max-tokens-must-be-positive","errorCode":null,"errorMessage":"max_tokens must be positive","messagePattern":"max_tokens must be positive","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/config/template/template.go","lineNumber":314,"sourceCode":"// and MEMORY_COMPRESSION_TASK).\nfunc (t *ScanTemplate) ApplyLanguage(lang string) {\n\tinstruction := \"\\n\\nAlways respond in \" + resolveLang(lang) + \".\"\n\tapplyLanguage(&t.MainTask, instruction)\n\tif t.PlanTask != nil {\n\t\tapplyLanguage(t.PlanTask, instruction)\n\t}\n\tif t.DedupTask != nil {\n\t\tapplyLanguage(t.DedupTask, instruction)\n\t}\n\tif t.ProjectSummaryTask != nil {\n\t\tapplyLanguage(t.ProjectSummaryTask, instruction)\n\t}\n\tapplyLanguage(&t.MemoryCompressionTask, instruction)\n}\n\nfunc (t *Template) Validate() error {\n\tif t.MaxTokens <= 0 {\n\t\treturn fmt.Errorf(\"max_tokens must be positive\")\n\t}\n\tif t.MaxToolRequestTimes <= 0 {\n\t\treturn fmt.Errorf(\"max_tool_request_times must be positive\")\n\t}\n\tif t.MaxReviewRounds < 0 {\n\t\treturn fmt.Errorf(\"max_review_rounds must not be negative\")\n\t}\n\tif len(t.MainTask.Messages) == 0 {\n\t\treturn fmt.Errorf(\"main_task.messages must not be empty\")\n\t}\n\treturn nil\n}\n\n// Validate checks that a ScanTemplate has the minimum fields populated.\nfunc (t *ScanTemplate) Validate() error {\n\tif t.MaxTokens <= 0 {\n\t\treturn fmt.Errorf(\"scan: max_tokens must be positive\")\n\t}","sourceCodeStart":296,"sourceCodeEnd":332,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/internal/config/template/template.go#L296-L332","documentation":"Template.Validate enforces invariants after a template is loaded or constructed. MaxTokens is the per-request token budget for the LLM; if it is zero or negative the request cannot be sized correctly, so Validate returns 'max_tokens must be positive'. Callers typically hit this after building a Template programmatically or from a manifest where MAX_TOKENS was absent/zero.","triggerScenarios":"Calling (*Template).Validate() when t.MaxTokens <= 0 — e.g. a hand-written templateManifest JSON missing MAX_TOKENS, a Template literal with MaxTokens unset, or code copying manifest fields while skipping MaxTokens.","commonSituations":"Creating a custom Template in Go and forgetting to set MaxTokens; a stripped-down custom task_template.json without MAX_TOKENS; copy-pasting template construction code that leaves the zero value; tests building a minimal Template to check another invariant.","solutions":["Set MaxTokens to a positive value appropriate for your model (e.g. 4096) before calling Validate","If loading from a manifest, add a MAX_TOKENS key with a positive integer to task_template.json and rebuild","Audit template-construction code paths to ensure every field assignment (MaxTokens, MaxToolRequestTimes, ...) is copied, not just the conversations","Call Validate() immediately after constructing/loading so the failure surfaces before any LLM request is attempted"],"exampleFix":"// before\ntpl := &template.Template{MaxToolRequestTimes: 5, MainTask: mainTask}\nif err := tpl.Validate(); err != nil { ... }\n// after\ntpl := &template.Template{MaxTokens: 4096, MaxToolRequestTimes: 5, MainTask: mainTask}\nif err := tpl.Validate(); err != nil { ... }","handlingStrategy":"validation","validationCode":"func checkTemplate(t *template.Template) error {\n\tif t == nil || t.MaxTokens <= 0 {\n\t\treturn fmt.Errorf(\"caller bug: MaxTokens must be > 0, got %d\", t.MaxTokens)\n\t}\n\treturn t.Validate()\n}","typeGuard":null,"tryCatchPattern":"if err := tpl.Validate(); err != nil {\n\tif strings.Contains(err.Error(), \"max_tokens must be positive\") {\n\t\ttpl.MaxTokens = 4096 // apply sane default\n\t\terr = tpl.Validate()\n\t}\n\tif err != nil { return err }\n}","preventionTips":["Always construct templates via LoadDefault rather than zero-value literals","Set every numeric budget field (MaxTokens, MaxToolRequestTimes, MaxReviewRounds) together","Call Validate immediately after any programmatic mutation of a Template"],"tags":["go","validation","config","template"],"backgroundTag":"invalid-config-value","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}