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

  1. Close the quoted string with a matching `"` on the same line.
  2. Escape literal quotes inside the value as \" (quotes cannot span lines).
  3. Remove quoting if the value has no spaces or tabs.
  4. 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

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


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/159d2ab8b5ff3c14. Report an issue: GitHub.