Troubleshooting
Most inputs diff quickly, but some are slow, and some edge cases produce results that need explanation. Each issue below lists the symptom, the cause, and a workaround.Diff is too slow
Symptom: Diffing a large tree or monorepo takes much longer than expected. Cause: Usually parsing, not matching. Tree matching is linear in node count (350k nodes in roughly 70 ms), and container matching at the bottom of the tree is O(n²) only in degenerate worst cases. The first parse of a huge file on a cold grammar cache dominates. Workaround: Diff specific files instead of whole directories. On a large repository, diffing one file is much faster than diffing a directory or the whole working tree.There is no node-count cap: every tree size is matched for real. If a pathological input is slow, it is slow on the parser side, not because matching gave up.
Deep nesting
The matcher walks trees with explicit stacks, not recursion. A 200,000-level-deep chain matches in about 100 ms with no stack overflow, and deeply nested JSON, HTML, and TypeScript all diff normally. If a runtime still crashes on some pathological nesting, the recursion is in a parser or the runtime itself (for exampleJSON.parse). Open an issue with the input that broke.
YAML diffs are wrong
Symptom: YAML diffs lose nesting, report spurious changes, or show flat structures that should be nested. Cause: The YAML parser requires 2-space indentation. YAML formatted with 4-space indentation (or tabs) can lose its nesting structure during parsing. Workaround: Reformat YAML to 2-space indentation before diffing.Renames show as delete + insert
Symptom: A renamed function or variable appears as a pair of Delete and Insert actions instead of a rename. Cause: Rename detection at the leaf level is a known limitation. Individual leaf nodes do not carry enough context for the matcher to pair them as renames. Workaround: This is largely cosmetic. The narration layer (@ossl-dev/differens-narrate) reads the surrounding context and phrases such changes as moves or renames in its prose output. That is the intended way to consume diffs, whether by humans or LLMs.
Markup parser misbehaves
Symptom: HTML/XML diffs are wrong, especially around attributes. Cause: The markup tokenizer (T3 tier) is regex-based, and it can misparse a> that appears inside an attribute value, for example <div title="a > b">. The tokenizer treats the > as closing the tag.
Workaround: Rewrite the attribute value so it does not contain a raw > (for example, use > or >), or diff the file with a different tier.
Build errors
Symptom:bun run build fails with missing module or resolve errors.
Cause: Dependencies were never installed, or the installed Bun version is too old. Differens requires Bun >= 1.3.
Workaround:
bun install again to refresh the lockfile and native bindings.
TypeScript errors
Symptom: Editor or CI reports type errors across packages. Cause: Stale build artifacts, or a change that broke a shared type across the monorepo. Workaround: Run the typechecker across all packages to see the full picture:Still stuck?
Open a GitHub issue at ossl-dev/differens with the command you ran, the input shape (file, directory, or commit range), and the output you saw. Known limitations are tracked inROADMAP.md at the repo root.