fs: fs.link() on exFAT volumes (Windows) fails with misleading EISDIR instead of "not supported"
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 55/100
- Tipo di issue
- Bug
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Attiva
- Stack tecnologico
- javascript, node.js
- Ambito
- operating-systems
Direzione di ricerca
Traccia fs.link e uv_fs_link attraverso il percorso Windows CreateHardLinkW, quindi esamina la mappatura di uv_translate_sys_error di libuv per ERROR_INVALID_FUNCTION. Conferma la mappatura con una riproduzione su exFAT e aggiungi un test di regressione che copra l’errno risultante; il lavoro è completato quando l’errore non segnala più EISDIR e identifica l’operazione non supportata.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
- Version: v24.19.0
- Platform: Windows 11 Home (10.0.22631), x64 — NTFS system drive; two USB exFAT volumes (4TB / 2TB)
- Subsystem: fs
What is wrong?
fs.linkSync(src, dest) targeting a file on an exFAT volume fails with errno EISDIR ("illegal operation on a directory"). The destination path does not exist and is not a directory. The real reason is that exFAT does not support hard links, and the underlying Win32 error is ERROR_INVALID_FUNCTION (WinError 1).
The EISDIR diagnosis actively misleads: it sends developers hunting for a directory that isn't there, instead of pointing at the unsupported filesystem operation.
Reproduction
On an exFAT-formatted volume (e.g. X:\):
$ node -e "require('fs').linkSync('X:\\a.tmp','X:\\b.tmp')"
Error: EISDIR: illegal operation on a directory, link 'X:\a.tmp' -> 'X:\b.tmp'
Python cross-check on the same volume shows the true underlying Win32 error:
$ python -c "import os; os.link(r'X:\a.tmp', r'X:\b.tmp')"
OSError: [WinError 1] 函数不正确。 (ERROR_INVALID_FUNCTION)
Observations from our test matrix (single machine, Windows 11 build 22631, Node v24.19.0):
| Target volume | Filesystem | fs.linkSync result |
|---|---|---|
| C:, D:, F: | NTFS | succeeds |
| E: (USB), H: (USB) | exFAT | always fails with EISDIR |
The failure splits perfectly along filesystem type, independent of internal/USB. Reads are unaffected; plain file writes work fine on exFAT.
Expected behavior
When CreateHardLinkW fails with ERROR_INVALID_FUNCTION on a filesystem without hard-link support, Node/libuv should surface a meaningful errno — e.g. ENOSYS ("function not implemented"), EPERM, or EOPNOTSUPP — rather than EISDIR.
For reference, on Linux, link(2) on filesystems that do not support hard links reports EPERM/EOPNOTSUPP, and on a system without the syscall at all ENOSYS.
Hypothesis (for upstream to confirm)
Possibly a missing mapping for ERROR_INVALID_FUNCTION in libuv's win32 uv_translate_sys_error, letting the failed uv_fs_link fall through to a misleading errno. We have not traced the exact layer; we only report the observed mapping WinError 1 (ERROR_INVALID_FUNCTION) → EISDIR.
Context / impact
This surfaced while diagnosing a third-party agent tool that publishes files via temp-file + hard-link: on exFAT drives every write failed, and the EISDIR message misattributed the cause. Reported downstream at https://github.com/deepseek-ai/deepseek-harness/discussions/5704 (includes the consumer-side analysis and a fallback-to-rename mitigation).
exFAT is the factory default format for many USB drives and SD cards, so "write to my external drive" is a common end-user scenario that hits this.
- Lingua principale
- JavaScript
- Stelle
- 122k
- Fork
- 37.4k
- Merge medio
- 4g 3h
- PR unite (30g)
- 279
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di nodejs/node
-
doc
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
-
build
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 90/100
-
feature request
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
-
Theme loads third-party resources on every page (jsdelivr web font, cdnjs Font Awesome) – GDPR Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
docToolchain/docToolchain#1705 ·
-
Timezone select lists one option per character; duplicate "Failed" reason; shared tracker popover id Apertabug
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
nightscout/nocturne#1414 ·
-
bug v2
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
modelcontextprotocol/inspector#2458 · 1 commento ·
-
Mend: dependency security vulnerability status: needs triage 🕵️♀️
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
carbon-design-system/ibm-products#9907 ·