{"record":{"id":"8729017fe754e78f","repo":"parcel-bundler/parcel","slug":"eloop","errorCode":"ELOOP","errorMessage":"ELOOP: ${path} is a symlink","messagePattern":"ELOOP: (.+?) is a symlink","errorType":"exception","errorClass":"FSError","httpStatus":null,"severity":"error","filePath":"packages/dev/repl/src/parcel/ExtendedMemoryFS.js","lineNumber":275,"sourceCode":"      if (candidate >= FD_MAX) {\n        this.nextFD = 1;\n        candidate = this.nextFD++;\n      }\n      if (!this.openFDs.has(candidate)) {\n        fd = candidate;\n        break;\n      }\n    }\n    if (!fd) {\n      throw new FSError('EMFILE', path, 'no available file descriptor');\n    }\n    return fd;\n  }\n\n  openSync(filePath: FilePath, flags: number, mode: number): number {\n    flags = parseOpenFlags(flags);\n    if (flags & CONSTANTS.O_NOFOLLOW && this.symlinks.has(filePath)) {\n      throw new FSError('ELOOP', filePath, 'is a symlink');\n    }\n\n    filePath = this._normalizePath(filePath);\n\n    let file = this.files.get(filePath);\n    if (flags & CONSTANTS.O_CREAT) {\n      if (file) {\n        if (flags & CONSTANTS.O_EXCL) {\n          throw new FSError('EEXIST', filePath, 'already exists');\n        }\n      } else {\n        file = new File(makeShared(''), mode);\n        this.files.set(filePath, file);\n      }\n    }\n    if (!file) {\n      throw new FSError('ENOENT', filePath, 'does not exist');\n    } else if (flags & CONSTANTS.O_TRUNC) {","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/parcel-bundler/parcel/blob/59484858a1a0bcbb71f74088956bb437a2db6505/packages/dev/repl/src/parcel/ExtendedMemoryFS.js#L257-L293","documentation":"ELOOP raised by `ExtendedMemoryFS.openSync` when `O_NOFOLLOW` is set in the flags and the target path is a symlink. Mirrors POSIX: O_NOFOLLOW forbids following symlinks at open time.","triggerScenarios":"Opening a path with the `O_NOFOLLOW` flag when that path is recorded as a symlink in the memory FS; defensive opens against an attacker-controlled path that turned out to be a link.","commonSituations":"Security-hardened code that uses O_NOFOLLOW to avoid symlink races; tooling that opens files written by a process that created symlinks.","solutions":["If following the link is intended, drop the `O_NOFOLLOW` flag.","If the path must be a regular file, reject or fix the symlink upstream before opening.","Resolve the real path first with `realpathSync` if you want the link target."],"exampleFix":"// before\nfs.openSync(symlinkPath, O_RDONLY | O_NOFOLLOW);  // ELOOP\n// after\nfs.openSync(symlinkPath, O_RDONLY);  // follow allowed","handlingStrategy":"validation","validationCode":"function openNoFollowSafe(fs, p, flags) {\n  if ((flags & O_NOFOLLOW) && fs.symlinks.has(p)) throw new Error(`${p} is a symlink`);\n  return fs.openSync(p, flags);\n}","typeGuard":"function isSymlink(fs, p) { return fs.symlinks.has(p); }","tryCatchPattern":"try { return fs.openSync(p, O_RDONLY | O_NOFOLLOW); }\ncatch (e) { if (e.code === 'ELOOP') return fs.openSync(p, O_RDONLY); throw e; }","preventionTips":["Drop O_NOFOLLOW when following symlinks is acceptable.","Resolve the real path with realpathSync first.","Reject symlinks upstream when O_NOFOLLOW is intentional."],"tags":["filesystem","memory-fs","symlink","eloop","repl"],"backgroundTag":null,"analyzedSha":"59484858a1a0bcbb71f74088956bb437a2db6505","analyzedAt":"2026-08-13T04:06:35.925Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}