gastownhall/beads · error
failed to render prompt: %w
Error message
failed to render prompt: %w
What it means
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.
Source
Thrown at internal/compact/haiku.go:84
aiMetricsOnce.Do(initAIMetrics)
return &haikuClient{
client: client,
model: config.DefaultAIModelFor(keySource),
apiKeySource: keySource,
baseURL: baseURL,
tier1Template: tier1Tmpl,
maxRetries: maxRetries,
initialBackoff: initialBackoff,
}, nil
}
// SummarizeTier1 creates a structured summary of an issue (Summary, Key Decisions, Resolution).
func (h *haikuClient) SummarizeTier1(ctx context.Context, issue *types.Issue) (string, error) {
prompt, err := h.renderTier1Prompt(issue)
if err != nil {
return "", fmt.Errorf("failed to render prompt: %w", err)
}
resp, callErr := h.callWithRetry(ctx, prompt)
if h.auditEnabled {
// Best-effort: never fail compaction because audit logging failed.
e := &audit.Entry{
Kind: "llm_call",
Actor: h.auditActor,
IssueID: issue.ID,
Model: h.model,
Prompt: prompt,
Response: resp,
}
if callErr != nil {
e.Error = callErr.Error()
}
_, _ = audit.Append(e) // Best effort: audit logging must never fail compaction
}View on GitHub (pinned to 71377f2769)
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
Example fix
// before
summary, err := client.SummarizeTier1(ctx, nil)
// after
if issue == nil {
return fmt.Errorf("cannot summarize nil issue %s", id)
}
summary, err := client.SummarizeTier1(ctx, issue) Defensive patterns
Strategy: validation
Validate before calling
if issue == nil || issue.ID == "" {
return errors.New("issue must be non-nil with an ID before SummarizeTier1")
}
summary, err := client.SummarizeTier1(ctx, issue) Type guard
func validIssue(i *types.Issue) bool { return i != nil && i.ID != "" } Try / catch
summary, err := client.SummarizeTier1(ctx, issue)
if err != nil && strings.Contains(err.Error(), "failed to render prompt") {
return fmt.Errorf("prompt rendering failed for %s: %w", issue.ID, err)
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- standalone expansion %q: %w
- failed to read template %s: %w
- invalid format template: %w
- template execution error: %w
- ensureProxiedServerConfig: render YAML: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/7490f9478f31b419.
Report an issue: GitHub.