gastownhall/beads · error
unterminated quoted string
Error message
unterminated quoted string
What it means
`tokenizeBatchLine` splits batch lines on whitespace and supports double-quoted strings. If the line ends while still inside a quoted section (no closing `"`), tokenization fails with this bare error, which `parseBatchScript` then wraps with the line number.
Source
Thrown at cmd/bd/batch.go:343
}
if c == '"' {
inQuote = true
hasToken = true
continue
}
if c == ' ' || c == '\t' {
if hasToken {
tokens = append(tokens, cur.String())
cur.Reset()
hasToken = false
}
continue
}
hasToken = true
cur.WriteByte(c)
}
if inQuote {
return nil, fmt.Errorf("unterminated quoted string")
}
if hasToken {
tokens = append(tokens, cur.String())
}
return tokens, nil
}
// runBatchOp dispatches a single parsed op against the shared transaction.
// It intentionally does NOT call any of the non-tx cobra handlers; it talks
// straight to storage.Transaction so everything joins the same SQL tx.
func runBatchOp(ctx context.Context, tx storage.Transaction, op batchOp) (batchOpResult, error) {
actorName := getActor()
result := batchOpResult{Line: op.line, Op: op.cmd}
switch op.cmd {
case "close":
if len(op.args) < 1 {
return result, fmt.Errorf("close requires <id>")
}View on GitHub (pinned to 71377f2769)
Solutions
- Close the quoted string with a matching `"` on the same line.
- Escape literal quotes inside the value as \" (quotes cannot span lines).
- Remove quoting if the value has no spaces or tabs.
- Use `bd batch --dry-run` to catch tokenization errors before execution.
Example fix
// before (batch file) create "Fix login bug // after create "Fix login bug"
Defensive patterns
Strategy: validation
Validate before calling
# Reject lines with an odd number of unescaped double quotes:
awk '{ line=$0; gsub(/\\./,"",line); n=gsub(/"/,"",line); if (n % 2 != 0) print "line " NR ": unterminated quote" }' batch.txt Try / catch
tokens, err := tokenizeBatchLine(line)
if err != nil {
if err.Error() == "unterminated quoted string" {
return fmt.Errorf("line %d: %w — quotes cannot span lines; escape as \\"", lineNo, err)
}
return nil, err
} Prevention
- Escape literal quotes inside values as \"; only \" and \\ are valid escapes.
- Keep quoted values on a single line — no multi-line strings in batch scripts.
- Generate quoted values via a helper that escapes `"` and `\\` automatically.
- Dry-run scripts before execution to surface tokenization errors early.
When it happens
Trigger: Any batch line containing an unmatched `"` — e.g. `update bd-1 "in progress` — where the closing quote is missing before end of line. Escape sequences \" and \\ are honored; no other backslash escapes end the quote.
Common situations: Shell quoting stripping a trailing quote; line truncation from editors or terminals; programmatic generation of scripts that interpolates descriptions containing quotes without escaping.
Related errors
- line %d: %w
- line %d: 'dep' requires a subcommand (add|remove)
- line %d: unknown dep subcommand %q (want add|remove)
- line %d: unsupported batch command %q (supported: close, upd
- parsing batch input: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/159d2ab8b5ff3c14.
Report an issue: GitHub.