{"record":{"id":"536c64c8b86b5ffe","repo":"alibaba/open-code-review","slug":"s-w","errorCode":null,"errorMessage":"%s: %w","messagePattern":"%s: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/config/template/template.go","lineNumber":210,"sourceCode":"\t\tdata, err := templateFS.ReadFile(\"prompts/\" + mm.PromptFile)\n\t\tif err != nil {\n\t\t\treturn LlmConversation{}, fmt.Errorf(\"read prompt file %q: %w\", mm.PromptFile, err)\n\t\t}\n\t\tconv.Messages[i] = ChatMessage{\n\t\t\tRole:    mm.Role,\n\t\t\tContent: strings.TrimRight(string(data), \"\\r\\n\"),\n\t\t}\n\t}\n\treturn conv, nil\n}\n\nfunc resolveOptionalConversation(m *manifestConversation, name string) (*LlmConversation, error) {\n\tif m == nil {\n\t\treturn nil, nil\n\t}\n\tconv, err := resolveConversation(*m)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"%s: %w\", name, err)\n\t}\n\treturn &conv, nil\n}\n\n// LoadDefault parses the embedded task_template.json and resolves prompt file references.\nfunc LoadDefault() (*Template, error) {\n\tdata, err := templateFS.ReadFile(\"task_template.json\")\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"read embedded task_template.json: %w\", err)\n\t}\n\tvar m templateManifest\n\tif err := json.Unmarshal(data, &m); err != nil {\n\t\treturn nil, fmt.Errorf(\"unmarshal task_template manifest: %w\", err)\n\t}\n\n\tvar tpl Template\n\ttpl.MaxTokens = m.MaxTokens\n\ttpl.MaxCompletionTokens = m.MaxCompletionTokens","sourceCodeStart":192,"sourceCodeEnd":228,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/internal/config/template/template.go#L192-L228","documentation":"resolveOptionalConversation wraps errors from resolveConversation with the logical conversation name, producing a two-layer message like `default: read prompt file \"x\": ...`. It exists so LoadDefault can report which named conversation (e.g. default/review) failed, not just the raw file error.","triggerScenarios":"LoadDefault passes a non-nil manifestConversation to resolveOptionalConversation and the inner resolveConversation fails (typically a missing prompts/ file, i.e. error 218), producing this wrapper.","commonSituations":"Same as error 218 — a manifest entry whose prompt file is missing from the embedded FS — but surfaced with the conversation name prefix, e.g. from a customized template manifest in a patched build.","solutions":["Look at the inner `read prompt file %q` message to find the actual missing file","Fix the PromptFile reference in task_template.json or add the file under prompts/ with go:embed coverage","Rebuild so the embedded template bundle matches the manifest","Restore the pristine task_template.json if it was hand-modified"],"exampleFix":"// before\n\"conversation\": { \"name\": \"default\", \"promptFile\": \"old_name.md\" }\n// after\n\"conversation\": { \"name\": \"default\", \"promptFile\": \"review_system.md\" }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"tpl, err := template.LoadDefault()\nif err != nil {\n    var name, inner string\n    // message shape: \"<conversation>: read prompt file %q: ...\"\n    if parts := strings.SplitN(err.Error(), \": read prompt file \", 2); len(parts) == 2 {\n        fmt.Fprintf(os.Stderr, \"conversation %q failed: %s\\n\", parts[0], parts[1])\n    }\n    return err\n}","preventionTips":["Read the conversation-name prefix to know which named conversation to fix","Validate the whole template manifest with a test before distributing patched builds","Keep template manifest and prompts/ directory changes in the same commit"],"tags":["go","template","error-wrapping","embed"],"backgroundTag":"missing-embedded-file","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}