概要
EPERM: operation not permitted は、Node.jsでファイルやディレクトリに対する操作が権限不足で拒否された場合に発生するエラーです。EACCESとは異なり、より厳格な権限制限(root権限でも不可など)を示します。
エラーメッセージ
Error: EPERM: operation not permitted, unlink 'C:\path\to\file'
Error: EPERM: operation not permitted, rename 'old.txt' -> 'new.txt'
Error: EPERM: operation not permitted, open '/System/file'
npm ERR! Error: EPERM: operation not permitted, mkdir 'C:\Program Files\nodejs'
原因
1. ファイルが他のプロセスで使用中(Windows)
1
2
3
4
| // ファイルが開かれたまま削除しようとする
const fs = require('fs');
const fd = fs.openSync('data.txt', 'r');
fs.unlinkSync('data.txt'); // EPERM: ファイルが使用中
|
2. システム保護されたファイル
macOSのSystem Integrity Protection (SIP) やWindowsのシステムファイル保護が原因です。
1
2
| // macOSでシステムファイルを変更しようとする
fs.writeFileSync('/System/Library/file.txt', 'data'); // EPERM
|
3. 読み取り専用ファイル
1
2
| # ファイルに読み取り専用属性がついている
chmod 444 file.txt
|
1
| fs.writeFileSync('file.txt', 'new content'); // EPERM
|
4. node_modulesの削除問題(Windows)
1
2
3
| # Windowsでよくある問題
rm -rf node_modules
# EPERM: operation not permitted
|
5. アンチウイルスソフトによるブロック
ファイル操作がアンチウイルスソフトによってブロックされる場合があります。
解決策
1. ファイルハンドルを閉じる
1
2
3
4
5
6
7
8
9
| const fs = require('fs');
// ファイルを開く
const fd = fs.openSync('data.txt', 'r');
const content = fs.readFileSync(fd, 'utf8');
// 必ず閉じてから削除
fs.closeSync(fd);
fs.unlinkSync('data.txt'); // OK
|
2. ストリームのクローズを待つ
1
2
3
4
5
6
7
8
9
10
| const fs = require('fs');
const stream = fs.createWriteStream('output.txt');
stream.write('data');
stream.end();
stream.on('close', () => {
// ストリームが閉じてから操作
fs.unlinkSync('output.txt');
});
|
3. ファイル属性の変更
1
2
3
4
5
| # 読み取り専用を解除
chmod 644 file.txt
# Windows(コマンドプロンプト)
attrib -r file.txt
|
4. node_modules削除(Windows)
1
2
3
4
5
6
7
8
| # 方法1: rimrafを使用
npx rimraf node_modules
# 方法2: cmdで削除
rd /s /q node_modules
# 方法3: PowerShellで削除
Remove-Item -Recurse -Force node_modules
|
5. 管理者権限で実行
1
2
3
4
5
| # Windows: 管理者として実行
# PowerShellを管理者として開く
# macOS/Linux
sudo node script.js
|
6. プロセスの確認と終了
1
2
3
4
5
| # ファイルを使用しているプロセスを確認(Linux/macOS)
lsof | grep filename
# Windows
handle.exe filename
|
7. リトライロジックの実装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| const fs = require('fs');
async function deleteWithRetry(path, maxRetries = 5) {
for (let i = 0; i < maxRetries; i++) {
try {
fs.unlinkSync(path);
return;
} catch (err) {
if (err.code === 'EPERM' && i < maxRetries - 1) {
// 少し待ってリトライ
await new Promise(r => setTimeout(r, 100 * (i + 1)));
continue;
}
throw err;
}
}
}
|
EACCESとEPERMの違い
| エラー | 意味 | 例 |
|---|
| EACCES | アクセス権限不足 | 他ユーザーのファイルへのアクセス |
| EPERM | 操作自体が許可されない | システム保護ファイル、ファイル使用中 |
1
2
3
4
5
| // EACCES: 権限を変更すれば解決可能
fs.readFileSync('/home/other_user/file.txt');
// EPERM: 権限だけでは解決できない場合がある
fs.unlinkSync('/System/Library/file.txt'); // SIP保護
|
関連エラー