Skip to content

Fix error that occurs when a diff swaps a file for a symlink - #67

Open
AJ-505 wants to merge 1 commit into
oxidecomputer:mainfrom
AJ-505:fix/symlink-typechange-crash
Open

Fix error that occurs when a diff swaps a file for a symlink#67
AJ-505 wants to merge 1 commit into
oxidecomputer:mainfrom
AJ-505:fix/symlink-typechange-crash

Conversation

@AJ-505

@AJ-505 AJ-505 commented Sep 6, 2026

Copy link
Copy Markdown

Problem

While using the app, I ran into a strange error:

Uncaught Error: CodeView.addItem: duplicate id "<filename>"
    at e.appendItemsInternal (index-Dm4RBqAJ.js:1540:86005)
    at e.setItems (index-Dm4RBqAJ.js:1540:85611)
    at index-Dm4RBqAJ.js:1540:144009
    at Vc (index-Dm4RBqAJ.js:9:91887)
    at ol (index-Dm4RBqAJ.js:9:96369)
    at xl (index-Dm4RBqAJ.js:9:105219)
    at ol (index-Dm4RBqAJ.js:9:96928)
    at xl (index-Dm4RBqAJ.js:9:105219)
    at ol (index-Dm4RBqAJ.js:9:96356)
    at xl (index-Dm4RBqAJ.js:9:105219) 

Upon investigation, I realised that this behaviour only occurred on a diff that had a file which became a symlink.

Solution

Git handles these cases (files -> symlinks) specially: It produces two chunks with the same name: One with the file deleted, and the other a new file entry with the link (the one-liner pointing to the file).

Example, say we had notes.txt that had one line, and is now symlinked to target.txt. The git diff output should look like this:

diff --git a/notes.txt b/notes.txt
deleted file mode 100644
index ce01362..0000000
--- a/notes.txt
+++ /dev/null
@@ -1 +0,0 @@
-hello
diff --git a/notes.txt b/notes.txt
new file mode 120000
index 0000000..4cbb553
--- /dev/null
+++ b/notes.txt
@@ -0,0 +1 @@
+target.txt

Thus, passing that directly to @pierre/diffs's CodeView threw a duplicate id error. The core fix is to merge the duplicates first before merging. Additionally, add guardrails on symlinks to ensure they do not get followed wrongly, or be commented on to ensure intended behavior persists.

Verification

npm run test

This fix also works for symlinks converted to files as well.

Git writes a file-to-symlink change as two diff blocks for one path, a
delete plus an add. The client turned each block into its own CodeView
item, both carrying the file name as id, and CodeView threw a duplicate
id error that blanked the whole page.

Fold same-name entries into one item with mergeDuplicateFiles before
they reach CodeView, keeping both hunks. The server already keys file
hashes by name, so one entry lines up.

Also stop following symlinks on the server: working-copy symlinks serve
their link target for hunk expansion, comments through a symlink are
refused instead of editing the target file, and shebang detection no
longer reads through links.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant