{"record":{"id":"071d1dfe9b2fff3f","repo":"gastownhall/beads","slug":"line-d-w","errorCode":null,"errorMessage":"line %d: %w","messagePattern":"line (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/batch.go","lineNumber":258,"sourceCode":"// non-comment line. It rejects unknown commands immediately so a bad script\n// fails before any writes.\nfunc parseBatchScript(r io.Reader) ([]batchOp, error) {\n\tscanner := bufio.NewScanner(r)\n\t// Allow long lines (descriptions, multi-token updates).\n\tscanner.Buffer(make([]byte, 64*1024), 4*1024*1024)\n\n\tvar ops []batchOp\n\tlineNo := 0\n\tfor scanner.Scan() {\n\t\tlineNo++\n\t\traw := scanner.Text()\n\t\ttrimmed := strings.TrimSpace(raw)\n\t\tif trimmed == \"\" || strings.HasPrefix(trimmed, \"#\") {\n\t\t\tcontinue\n\t\t}\n\t\ttokens, err := tokenizeBatchLine(trimmed)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"line %d: %w\", lineNo, err)\n\t\t}\n\t\tif len(tokens) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\top := batchOp{line: lineNo, raw: trimmed}\n\t\tswitch tokens[0] {\n\t\tcase \"close\":\n\t\t\top.cmd = \"close\"\n\t\t\top.args = tokens[1:]\n\t\tcase \"update\":\n\t\t\top.cmd = \"update\"\n\t\t\top.args = tokens[1:]\n\t\tcase \"create\":\n\t\t\top.cmd = \"create\"\n\t\t\top.args = tokens[1:]\n\t\tcase \"dep\":\n\t\t\tif len(tokens) < 2 {\n\t\t\t\treturn nil, fmt.Errorf(\"line %d: 'dep' requires a subcommand (add|remove)\", lineNo)","sourceCodeStart":240,"sourceCodeEnd":276,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/batch.go#L240-L276","documentation":"`parseBatchScript` tokenizes each non-blank, non-comment line of a batch script; if `tokenizeBatchLine` fails (currently only for an unterminated quoted string), the error is wrapped with the 1-based line number. Parsing happens fully before any writes, so a tokenization error aborts the entire batch with no side effects.","triggerScenarios":"A batch script line contains an opening double quote that is never closed, e.g. `update bd-1 \"half done` piped to `bd batch` or passed via `-f script.txt`.","commonSituations":"Descriptions containing quotes where the closing quote got lost by shell escaping; heredocs/CI scripts with truncated lines; generating batch files programmatically without escaping `\"` inside quoted values.","solutions":["Go to the reported line number and close the opening double quote.","Escape embedded quotes as \\\" inside double-quoted strings.","If the quote is unnecessary, remove it — quoting is only needed for values with spaces/tabs.","Run `bd batch --dry-run` to validate the whole script before executing."],"exampleFix":"// before (batch file)\nupdate bd-1 \"status in review\n// after\nupdate bd-1 \"status in review\"","handlingStrategy":"validation","validationCode":"# Validate the batch script before executing:\nbd batch --dry-run -f batch.txt || echo \"fix the reported line\"\n# Or check quoting per line in shell:\nawk '{ n=gsub(/\"/,\"\",$0); if (n % 2 != 0) print \"unbalanced quote at line \" NR \": \" $0 }' batch.txt","typeGuard":null,"tryCatchPattern":"ops, err := parseBatchInput(r)\nif err != nil {\n    if strings.Contains(err.Error(), \"line \") {\n        return fmt.Errorf(\"batch script rejected before any writes: %w\", err)\n    }\n    return err\n}","preventionTips":["Always smoke-test scripts with `--dry-run`.","Escape embedded quotes as \\\" when generating scripts programmatically.","Avoid hand-written quoting: prefer generating lines without spaces needing quotes.","Check heredocs/CI files for truncated lines before piping to `bd batch`."],"tags":["cli","batch","parsing","go"],"backgroundTag":"batch-script-parse-error","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}