MoonshotAI / MoonshotAI/kimi-code
[Bug] Trailing backslash degrades the whole bash parse to a single ERROR node
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 7.5k
- Forks
- 1.2k
- Avg merge
- 11h 53m
- Merged PRs (30d)
- 350
Description
What version of Kimi Code is running?
Reproduced on main at commit d1a46db94 (package @moonshot-ai/tree-sitter-bash).
Which open platform/subscription were you using?
N/A — this is a code-level correctness bug in the @moonshot-ai/tree-sitter-bash parser, found by source review and reproduced with a unit test. It is not tied to a plan or model.
Which model were you using?
N/A
What platform is your computer?
macOS (Darwin arm64). The bug is platform-independent — the parser is pure TypeScript.
What issue are you seeing?
parse() degrades a perfectly valid command whose scan range ends in a lone backslash into a single whole-source ERROR node (hasError: true), losing all structure.
On current main:
parse('echo \')returns a root that is a singleERROR [0,6)instead ofcommand(command_name(word "echo"), word "\"). InternallySyntaxNodeBuilderthrowsRangeError: invalid node range [0, 7) for source of length 6, andparse()'s last-resortcatchinsrc/parse.tsconverts that into the whole-sourceERRORnode.- The same happens for
\,[[ -f x && \, andcase x in a\.
What steps can reproduce the bug?
In packages/tree-sitter-bash:
import { parse } from '#/parse';
const r = parse('echo \\'); // the string: echo, space, one backslash
// expected: ok:true, hasError:false — a command with a trailing word "\"
// actual: ok:true, hasError:true — root is a single whole-source ERROR node
This is not fuzzer-only: test/fixtures/corpus/statements.txt already contains a real line ending in a continuation backslash, so any consumer that parses a single line before the following newline arrives hits it.
What is the expected behavior?
A lone trailing backslash is kept as word text — which is exactly what scanWord's own comment in src/lexer.ts says should happen. echo \ should parse to a normal command with a trailing word "\" and hasError: false; the test-command and case inputs should error-recover locally rather than collapsing the whole tree.
Additional information
Root cause: four character scanners skip an escaped character with idx += 2. When the backslash is the last character of the scan range, that overshoots to end + 1, so the emitted node endIndex exceeds the source length (or the parent's end) and SyntaxNodeBuilder rejects it. The four sites are scanWord (src/lexer.ts) and scanCasePatternEnd / scanTestToken / scanTestCloser (src/parser.ts).
Proposed fix: clamp the skip to the scan bound, idx = Math.min(idx + 2, end). The clamp is a no-op unless the backslash is the final character, so no other parse changes. I verified locally that the full tree-sitter-bash suite — including the differential comparison against the reference tree-sitter-bash corpus — stays green, and added regression cases that fail before the change and pass after it.
I'm happy to open the PR once this is approved.
Contribution
- I am willing to submit a PR for this bug fix myself (please wait for maintainer approval in this issue first)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in packages/tree-sitter-bash/src/lexer.ts and src/parser.ts, focusing on the four character scanners named in the issue, then inspect the regression cases in test/fixtures/corpus/statements.txt. Run the tree-sitter-bash test suite and confirm trailing backslashes preserve the command structure while malformed test-command and case inputs recover locally instead of becoming one whole-source ERROR node.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- bash, typescript
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 82/100