gastownhall/beads · error
loading attachment %s: %w
Error message
loading attachment %s: %w
What it means
After the --attach argument resolves to an ID, bd mol pour loads that attachment issue with GetIssue before validating it. This error wraps a failed load, preserving the cause. The ID resolved, but the issue could not be fetched — storage failure, concurrent deletion, or the attachment being a wisp invisible to GetIssue.
Source
Thrown at cmd/bd/mol_proxied_server.go:89
if err != nil {
return pourProxiedResult{}, "", fmt.Errorf("loading proto: %w", err)
}
}
type attachmentInfo struct {
id string
issue *types.Issue
subgraph *TemplateSubgraph
}
var attachments []attachmentInfo
for _, attachArg := range in.attachArgs {
attachID, err := utils.ResolvePartialID(ctx, w, attachArg)
if err != nil {
return pourProxiedResult{}, "", fmt.Errorf("resolving attachment ID %s: %w", attachArg, err)
}
attachIssue, err := w.GetIssue(ctx, attachID)
if err != nil {
return pourProxiedResult{}, "", fmt.Errorf("loading attachment %s: %w", attachID, err)
}
if !isProto(attachIssue) {
return pourProxiedResult{}, "", fmt.Errorf("%s is not a proto (missing '%s' label)", attachID, MoleculeLabel)
}
attachSubgraph, err := loadTemplateSubgraph(ctx, w, attachID)
if err != nil {
return pourProxiedResult{}, "", fmt.Errorf("loading attachment subgraph %s: %w", attachID, err)
}
attachments = append(attachments, attachmentInfo{attachID, attachIssue, attachSubgraph})
}
vars := applyVariableDefaults(vars, subgraph)
var attachSubgraphs []*TemplateSubgraph
for _, a := range attachments {
attachSubgraphs = append(attachSubgraphs, a.subgraph)
}
if err := checkPourVars(subgraph, attachSubgraphs, vars); err != nil {View on GitHub (pinned to 71377f2769)
Solutions
- Re-run the command — transient races/locks often resolve on retry
- Confirm the attachment exists: bd show <attachID>
- Ensure the attachment is a persistent (non-wisp) issue
- Check for and wait out concurrent bd processes holding the DB lock
Example fix
// before
attachIssue, err := w.GetIssue(ctx, attachID)
if err != nil { return fmt.Errorf("loading attachment %s: %w", attachID, err) }
// after: distinguish not-found from transient
attachIssue, err := w.GetIssue(ctx, attachID)
if err != nil {
if errors.Is(err, sql.ErrNoRows) { return fmt.Errorf("attachment %s no longer exists", attachID) }
return fmt.Errorf("loading attachment %s: %w", attachID, err)
} Defensive patterns
Strategy: retry
Validate before calling
// verify each attachment is loadable before pouring
for _, id := range attachIDs {
if _, err := reader.GetIssue(ctx, id); err != nil {
return fmt.Errorf("attachment %s not loadable: %w", id, err)
}
} Try / catch
err := pourCmd(args)
if err != nil && strings.Contains(err.Error(), "loading attachment ") {
time.Sleep(time.Second)
err = pourCmd(args) // retry transient storage failures once
} Prevention
- Avoid deleting attachments while pours using them are running
- Use persistent (non-wisp) issues as attachments
- Serialize concurrent bd operations to prevent DB locks
- Re-check existence with bd show on repeated failures
When it happens
Trigger: Running `bd mol pour <proto> --attach <id>` where GetIssue fails after successful ID resolution: concurrent deletion of the attachment, Dolt lock/corruption, context timeout, or ephemeral wisp attachments not loadable via the normal issue path.
Common situations: Another agent removed the attachment between resolve and load; database locked by concurrent bd commands; attaching an ephemeral issue that gc'ed mid-operation.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- loading proto %s: %w
- loading proto: %w
- loading attachment subgraph %s: %w
- pouring proto: %w
- loading spawned mol: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/f4f5c338f90af921.
Report an issue: GitHub.