Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fs.writeFileSync in Node 20 failed to write file in TMPDIR #52079

Closed
fannheyward opened this issue Mar 14, 2024 · 5 comments · Fixed by #52101
Closed

fs.writeFileSync in Node 20 failed to write file in TMPDIR #52079

fannheyward opened this issue Mar 14, 2024 · 5 comments · Fixed by #52101
Labels
fs Issues and PRs related to the fs subsystem / file system.

Comments

@fannheyward
Copy link

fannheyward commented Mar 14, 2024

Version

v20.11.1

Platform

macOS arm64

Subsystem

No response

What steps will reproduce the bug?

fs.writeFileSync failed to EACCES: permission denied error with Node 20, but works with Node 18.

import fs from 'fs'
import path from 'path'
import os from 'os'

function modify(fsPath, key, value) {
  let dir = path.dirname(fsPath)
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true })
  let content = fs.readFileSync(fsPath, { encoding: 'utf8', flag: 'a+' })
  content = content || '{}'
  content = JSON.parse(content)
  content[key] = value
  content = JSON.stringify(content)
  fs.writeFileSync(fsPath, content)
}

const p = path.join(os.tmpdir(), 'test', 'foo.json')
modify(p, 'key', 'foobar')

How often does it reproduce? Is there a required condition?

No response

What is the expected behavior? Why is that the expected behavior?

No response

What do you see instead?

❯ /opt/homebrew/opt/node@20/bin/node x.mjs
node:fs:2352
    return binding.writeFileUtf8(
                   ^

Error: EACCES: permission denied, open '/private/var/folders/7q/r_8_1r5d5bb0dfycljk5pr1h0000gn/T/test/foo.json'
    at Object.writeFileSync (node:fs:2352:20)
    at modify (file:///Users/fannheyward/x.mjs:13:6)
    at file:///Users/fannheyward/x.mjs:17:1
    at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:329:24)
    at async loadESM (node:internal/process/esm_loader:28:7)
    at async handleMainPromise (node:internal/modules/run_main:113:12) {
  errno: -13,
  code: 'EACCES',
  syscall: 'open',
  path: '/private/var/folders/7q/r_8_1r5d5bb0dfycljk5pr1h0000gn/T/test/foo.json'
}

Node.js v20.11.1

❯ ls -lh /private/var/folders/7q/r_8_1r5d5bb0dfycljk5pr1h0000gn/T/test/foo.json
----------  1 fannheyward  staff     0B  3 14 12:38 /private/var/folders/7q/r_8_1r5d5bb0dfycljk5pr1h0000gn/T/test/foo.json

Works with Node 18:

~ 
❯ /opt/homebrew/opt/node@18/bin/node x.mjs

❯ ls -lh /private/var/folders/7q/r_8_1r5d5bb0dfycljk5pr1h0000gn/T/test/foo.json
-rw-r--r--@ 1 fannheyward  staff    16B  3 14 12:36 /private/var/folders/7q/r_8_1r5d5bb0dfycljk5pr1h0000gn/T/test/foo.json

Additional information

No response

@atlowChemi atlowChemi added the fs Issues and PRs related to the fs subsystem / file system. label Mar 14, 2024
@fannheyward
Copy link
Author

Works as expected with node-v20.7.0, failed with node-v20.8.0+.

@fannheyward
Copy link
Author

fannheyward commented Mar 14, 2024

Change encoding utf8 to UTF8 or UTF-8 works, but tsserver reports encoding shouldn't be upper UTF, what's the problem?

Maybe #49884 related?

Update: this works too.

let content = fs.readFileSync(fsPath, { encoding: 'utf8', flag: 'a+' })

to

let content = fs.readFileSync(fsPath, { flag: 'a+' }).toString('utf8')

fannheyward added a commit to neoclide/coc.nvim that referenced this issue Mar 14, 2024
fannheyward added a commit to neoclide/coc.nvim that referenced this issue Mar 14, 2024
fannheyward added a commit to neoclide/coc.nvim that referenced this issue Mar 14, 2024
@richardlau
Copy link
Member

richardlau commented Mar 14, 2024

❯ /opt/homebrew/opt/node@20/bin/node x.mjs
node:fs:2352
    return binding.writeFileUtf8(
                   ^

Error: EACCES: permission denied, open '/private/var/folders/7q/r_8_1r5d5bb0dfycljk5pr1h0000gn/T/test/foo.json'
    at Object.writeFileSync (node:fs:2352:20)
    at modify (file:///Users/fannheyward/x.mjs:13:6)
    at file:///Users/fannheyward/x.mjs:17:1
    at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:329:24)
    at async loadESM (node:internal/process/esm_loader:28:7)
    at async handleMainPromise (node:internal/modules/run_main:113:12) {
  errno: -13,
  code: 'EACCES',
  syscall: 'open',
  path: '/private/var/folders/7q/r_8_1r5d5bb0dfycljk5pr1h0000gn/T/test/foo.json'
}

Node.js v20.11.1

❯ ls -lh /private/var/folders/7q/r_8_1r5d5bb0dfycljk5pr1h0000gn/T/test/foo.json
----------  1 fannheyward  staff     0B  3 14 12:38 /private/var/folders/7q/r_8_1r5d5bb0dfycljk5pr1h0000gn/T/test/foo.json

This looks similar to #50989 but #50990 should already be in Node.js 20.11.0.
cc @nodejs/fs

@richardlau
Copy link
Member

Seems to fail on Linux with Node.js 21.7.1 as well.

$ nvm run 21 x.mjs
Running node v21.7.1 (npm v10.5.0)
node:fs:2342
    return binding.writeFileUtf8(
                   ^

Error: EACCES: permission denied, open '/tmp/test/foo.json'
    at Object.writeFileSync (node:fs:2342:20)
    at modify (file:///tmp/writetest/x.mjs:13:6)
    at file:///tmp/writetest/x.mjs:17:1
    at ModuleJob.run (node:internal/modules/esm/module_job:222:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:323:24)
    at async loadESM (node:internal/process/esm_loader:28:7)
    at async handleMainPromise (node:internal/modules/run_main:120:12) {
  errno: -13,
  code: 'EACCES',
  syscall: 'open',
  path: '/tmp/test/foo.json'
}

Node.js v21.7.1
$

@richardlau
Copy link
Member

The regression is in fs.readFileSync() and was introduced by #49691. Opened #52101 to fix.

nodejs-github-bot pushed a commit that referenced this issue Mar 18, 2024
Fix a file permissions regression when `fs.readFileSync()` is called in
append mode on a file that does not already exist introduced by the
fast path for utf8 encoding.

PR-URL: #52101
Fixes: #52079
Refs: #49691
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br>
Reviewed-By: Yagiz Nizipli <yagiz.nizipli@sentry.io>
rdw-msft pushed a commit to rdw-msft/node that referenced this issue Mar 26, 2024
Fix a file permissions regression when `fs.readFileSync()` is called in
append mode on a file that does not already exist introduced by the
fast path for utf8 encoding.

PR-URL: nodejs#52101
Fixes: nodejs#52079
Refs: nodejs#49691
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br>
Reviewed-By: Yagiz Nizipli <yagiz.nizipli@sentry.io>
marco-ippolito pushed a commit that referenced this issue May 2, 2024
Fix a file permissions regression when `fs.readFileSync()` is called in
append mode on a file that does not already exist introduced by the
fast path for utf8 encoding.

PR-URL: #52101
Fixes: #52079
Refs: #49691
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br>
Reviewed-By: Yagiz Nizipli <yagiz.nizipli@sentry.io>
marco-ippolito pushed a commit that referenced this issue May 3, 2024
Fix a file permissions regression when `fs.readFileSync()` is called in
append mode on a file that does not already exist introduced by the
fast path for utf8 encoding.

PR-URL: #52101
Fixes: #52079
Refs: #49691
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br>
Reviewed-By: Yagiz Nizipli <yagiz.nizipli@sentry.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fs Issues and PRs related to the fs subsystem / file system.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants