nodejs / nodejs/node

fs: fs.link() on exFAT volumes (Windows) fails with misleading EISDIR instead of "not supported"

Ouverte
#65,817 6 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

Langage dominant
JavaScript
Étoiles
122k
Forks
37.3k
Merge moyen
4 j 2 h
PR mergées (30 j)
283

Description

  • 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.

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Suivez fs.link et uv_fs_link à travers le chemin Windows CreateHardLinkW, puis examinez la correspondance de uv_translate_sys_error de libuv pour ERROR_INVALID_FUNCTION. Confirmez la correspondance avec une reproduction sur exFAT et ajoutez un test de régression couvrant l’errno obtenu ; le travail est terminé lorsque l’erreur ne signale plus EISDIR et identifie l’opération non prise en charge.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
javascript, node.js
Domaine
operating-systems
Type d'issue
Bug
Difficulté
4/5
Temps estimé
3-5 jours
Activité
Active
Clarté
Plutôt claire
Accessibilité débutants
55/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.