gastownhall/beads · error
line %d (%s): %w
Error message
line %d (%s): %w
What it means
During `bd batch` execution, each parsed operation runs inside a single storage transaction; if `runBatchOp` fails for any op, the whole transaction is rolled back and the error is wrapped with the source line number and the raw line text. This lets you locate the exact failing command in a batch script while preserving the underlying storage error. All prior ops in the batch are discarded (atomic batch semantics).
Source
Thrown at cmd/bd/batch.go:181
ctx := rootCtx
if ctx == nil {
ctx = context.Background()
}
// One transaction, one commit message, whole-batch rollback on the first
// failing line — the contract is the same on both backends; only the
// transaction primitive differs (uow.RunTx there, transact here), and
// both wrap a per-op dispatch that shares this file's parser.
var results []batchOpResult
if proxied {
results, err = runBatchProxiedServer(ctx, ops, commitMsg)
} else {
results = make([]batchOpResult, 0, len(ops))
err = transact(ctx, store, commitMsg, func(tx storage.Transaction) error {
for _, op := range ops {
res, rerr := runBatchOp(ctx, tx, op)
if rerr != nil {
return fmt.Errorf("line %d (%s): %w", op.line, op.raw, rerr)
}
results = append(results, res)
}
return nil
})
}
if err != nil {
if jsonOutput {
if jerr := outputJSONError(err, "batch_error"); jerr != nil {
return errors.Join(err, jerr)
}
}
return err
}
commandDidWrite.Store(true)
if jsonOutput {View on GitHub (pinned to 71377f2769)
Solutions
- Read the wrapped 'line %d (%s)' prefix to find the failing line in your batch script and fix the command there (usually a bad issue ID).
- Verify referenced issue IDs exist with `bd show <id>` before batching.
- Split the batch file to isolate the failing op; note no partial commits happen — fix and re-run the whole file.
- Check the inner %w error for the storage-level cause (e.g. 'not found', constraint violation).
Example fix
// before (batch file) close bd-1042 close bd-9999 <- not found // after close bd-1042 close bd-1043 <- verified existing ID
Defensive patterns
Strategy: try-catch
Validate before calling
# Before running the batch, verify all referenced IDs exist: bd list --json | jq -r '.[].id' | sort > /tmp/known.ids grep -oE 'bd-[0-9]+' batch.txt | sort -u | while read id; do grep -qx "$id" /tmp/known.ids || echo "missing: $id"; done
Try / catch
err := bdBatch(scriptFile)
if err != nil {
var lineErr interface{ Line() int }
if m := regexp.MustCompile(`line (\d+) \((.*)\): (.*)`).FindStringSubmatch(err.Error()); m != nil {
log.Fatalf("batch failed at line %s (%s): %s — nothing was committed", m[1], m[2], m[3])
}
return err
} Prevention
- Run `bd batch --dry-run` first; note it parses only — verify IDs against `bd list` separately.
- Generate batch files from a query of existing issue IDs rather than hardcoding them.
- Treat batches as all-or-nothing: fix the reported line and re-run the entire file.
- Keep batch scripts in version control so failed runs are reproducible.
When it happens
Trigger: Running `bd batch` (from a file via -f or piped stdin) where an individual operation fails inside `runBatchOp` — e.g. `close bd-999` for a nonexistent issue ID, an `update` with invalid field values, or a `dep add` referencing missing issues.
Common situations: Batch scripts generated against an older database where referenced issue IDs no longer exist; typos in issue IDs inside large batch files; dependency edges that violate constraints (e.g. cycles or self-dependencies); scripts copied from another repo with different issue IDs.
Related errors
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/296e1a8973c9ad72.
Report an issue: GitHub.