{"record":{"id":"7490f9478f31b419","repo":"gastownhall/beads","slug":"failed-to-render-prompt-w","errorCode":null,"errorMessage":"failed to render prompt: %w","messagePattern":"failed to render prompt: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/compact/haiku.go","lineNumber":84,"sourceCode":"\n\taiMetricsOnce.Do(initAIMetrics)\n\n\treturn &haikuClient{\n\t\tclient:         client,\n\t\tmodel:          config.DefaultAIModelFor(keySource),\n\t\tapiKeySource:   keySource,\n\t\tbaseURL:        baseURL,\n\t\ttier1Template:  tier1Tmpl,\n\t\tmaxRetries:     maxRetries,\n\t\tinitialBackoff: initialBackoff,\n\t}, nil\n}\n\n// SummarizeTier1 creates a structured summary of an issue (Summary, Key Decisions, Resolution).\nfunc (h *haikuClient) SummarizeTier1(ctx context.Context, issue *types.Issue) (string, error) {\n\tprompt, err := h.renderTier1Prompt(issue)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to render prompt: %w\", err)\n\t}\n\n\tresp, callErr := h.callWithRetry(ctx, prompt)\n\tif h.auditEnabled {\n\t\t// Best-effort: never fail compaction because audit logging failed.\n\t\te := &audit.Entry{\n\t\t\tKind:     \"llm_call\",\n\t\t\tActor:    h.auditActor,\n\t\t\tIssueID:  issue.ID,\n\t\t\tModel:    h.model,\n\t\t\tPrompt:   prompt,\n\t\t\tResponse: resp,\n\t\t}\n\t\tif callErr != nil {\n\t\t\te.Error = callErr.Error()\n\t\t}\n\t\t_, _ = audit.Append(e) // Best effort: audit logging must never fail compaction\n\t}","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/compact/haiku.go#L66-L102","documentation":"SummarizeTier1 renders the issue into the tier-1 prompt using renderTier1Prompt before calling the AI. If template execution fails (missing field, wrong data shape, or the template itself was patched), the error is wrapped as \"failed to render prompt\". No API call is made in this case.","triggerScenarios":"h.renderTier1Prompt(issue) returns an error inside SummarizeTier1 — template.Execute failure on a *types.Issue, e.g. a nil issue pointer or a field the template references that errors under a custom Executor.","commonSituations":"Passing a nil *types.Issue to SummarizeTier1; locally modified template referencing a field removed from types.Issue after a version upgrade; custom data with missing keys when the template was refactored.","solutions":["Ensure the *types.Issue passed to SummarizeTier1 is non-nil and fully hydrated (ID, Title, Description set)","Inspect the wrapped cause for the exact template executor message and field name","Rebuild against a matching version of types.Issue if you upgraded the codebase","If you customized tier1PromptTemplate, update it for the current struct fields"],"exampleFix":"// before\nsummary, err := client.SummarizeTier1(ctx, nil)\n// after\nif issue == nil {\n\treturn fmt.Errorf(\"cannot summarize nil issue %s\", id)\n}\nsummary, err := client.SummarizeTier1(ctx, issue)","handlingStrategy":"validation","validationCode":"if issue == nil || issue.ID == \"\" {\n\treturn errors.New(\"issue must be non-nil with an ID before SummarizeTier1\")\n}\nsummary, err := client.SummarizeTier1(ctx, issue)","typeGuard":"func validIssue(i *types.Issue) bool { return i != nil && i.ID != \"\" }","tryCatchPattern":"summary, err := client.SummarizeTier1(ctx, issue)\nif err != nil && strings.Contains(err.Error(), \"failed to render prompt\") {\n\treturn fmt.Errorf(\"prompt rendering failed for %s: %w\", issue.ID, err)\n}","preventionTips":["Always hydrate the issue from the store before summarizing","Keep the template and types.Issue in sync across upgrades","Nil-check the issue at call sites"],"tags":["template","compaction","prompt"],"backgroundTag":"template-parse-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}