gastownhall/beads · error
insert issue into %s: %w
Error message
insert issue into %s: %w
What it means
This error is returned by executeIssueInsert when the raw INSERT of an issue row into the given table fails. It wraps the driver error with the target table name so you know which issue table rejected the insert. Common causes are constraint violations (duplicate primary key, NOT NULL), oversized values, or malformed column data.
Source
Thrown at internal/storage/issueops/helpers.go:157
?, ?, ?, ?,
?, ?, ?,
?, ?
)
%s
`, table, suffix),
issue.ID, issue.ContentHash, issue.Title, issue.Description, issue.Design, issue.AcceptanceCriteria, issue.Notes,
issue.Status, issue.Priority, issue.IssueType, NullString(issue.Assignee), NullInt(issue.EstimatedMinutes),
issue.CreatedAt, issue.CreatedBy, issue.Owner, issue.UpdatedAt, issue.StartedAt, issue.ClosedAt, NullStringPtr(issue.ExternalRef), issue.SpecID,
issue.CompactionLevel, issue.CompactedAt, NullStringPtr(issue.CompactedAtCommit), NullIntVal(issue.OriginalSize),
issue.Sender, issue.Ephemeral, issue.NoHistory, issue.WispType, issue.Pinned, issue.IsTemplate,
issue.MolType, issue.WorkType, issue.SourceSystem, issue.SourceRepo, issue.CloseReason, issue.ClosedBySession,
issue.EventKind, issue.Actor, issue.Target, issue.Payload,
issue.AwaitType, issue.AwaitID, issue.Timeout.Nanoseconds(), FormatJSONStringArray(issue.Waiters),
issue.DueAt, issue.DeferUntil, JSONMetadata(issue.Metadata),
freshRowLock(), NullString(string(issue.StorageClass.Normalize())),
)
if err != nil {
return fmt.Errorf("insert issue into %s: %w", table, err)
}
return nil
}
// RecordEventInTable records an event in the specified events table.
func RecordEventInTable(ctx context.Context, tx DBTX, table, issueID string, eventType types.EventType, actor, newValue string) error {
return InsertDerivedEvent(ctx, tx, table, AuxEvent{
IssueID: issueID,
EventType: eventType,
Actor: actor,
OldValue: str(""),
NewValue: str(newValue),
})
}
// GenerateIssueIDInTable generates a unique ID, checking for collisions
// in the specified table. Supports counter mode for non-ephemeral issues.
//View on GitHub (pinned to 71377f2769)
Solutions
- Read the wrapped driver error: 'UNIQUE constraint failed' means duplicate ID — generate a new ID instead of reusing it
- Check that the target table exists and has the expected columns (schema migration state)
- Validate issue fields before insert: non-empty ID, valid Metadata JSON, sane DueAt/DeferUntil values
- If create-only semantics are intended, use insertIssueCreateOnly handling and treat duplicate errors as an 'already exists' outcome
Example fix
// before
err := executeIssueInsert(ctx, tx, table, issue)
if err != nil {
return fmt.Errorf("insert issue into %s: %w", table, err)
}
// after
err := executeIssueInsert(ctx, tx, table, issue)
if err != nil {
if strings.Contains(err.Error(), "UNIQUE constraint failed") {
return ErrIssueExists // map duplicate to a typed sentinel
}
return fmt.Errorf("insert issue into %s: %w", table, err)
} Defensive patterns
Strategy: validation
Validate before calling
// validate before insert
if issue.ID == "" {
return errors.New("issue ID is empty")
}
var count int
if err := tx.QueryRowContext(ctx, `SELECT COUNT(*) FROM issues WHERE id = ?`, issue.ID).Scan(&count); err != nil {
return err
}
if count > 0 {
return ErrIssueExists
}
if _, err := json.Marshal(issue.Metadata); err != nil {
return fmt.Errorf("invalid metadata: %w", err)
} Try / catch
err := insertIssueIntoTable(ctx, tx, "issues", issue)
if err != nil {
if errors.Is(err, ErrIssueExists) || strings.Contains(err.Error(), "UNIQUE constraint failed") {
// handle already-exists path (load or skip)
return ErrIssueExists
}
return err
} Prevention
- Always generate a fresh ID (GenerateIssueIDInTable or counter mode) rather than reusing IDs from imports
- Validate Metadata is JSON-serializable before insert
- Keep schema migrations in lockstep with code versions
- Check available disk space / read-only status for embedded databases
When it happens
Trigger: Calling insertIssueIntoTable or insertIssueCreateOnly when: the issue ID already exists (duplicate PK), a required column is NULL, the metadata JSON produced by JSONMetadata is invalid for the column type, the row exceeds storage limits, or the table doesn't exist (unmigrated schema).
Common situations: Re-creating an issue with a colliding ID after import; writing issues into an old database missing newer columns after a version upgrade; metadata containing characters that break the JSON encoding; disk-full or read-only database in embedded mode.
Related errors
- db: CommentSQLRepository.Insert: %w
- update issue ID: %w
- insert compaction snapshot: %w
- add label: %w
- failed to begin transaction: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/ecb38fa8703673c7.
Report an issue: GitHub.