HeyPuter/puter · error · HttpError
cannot_write_to_root
cannot_write_to_root
Error message
Cannot write to root path
What it means
Thrown by FSController.#assertWriteAccess when the normalized target path is exactly `/`. Writing to the filesystem root is forbidden — root is the per-user mount namespace, not a writable location. This 400 (legacyCode `cannot_write_to_root`) fires before any ACL check, because no actor is ever permitted to write there.
Source
Thrown at src/backend/controllers/fs/FSController.ts:2333
): Promise<void> {
const actor = req.actor;
if (!actor) {
throw new HttpError(401, 'Unauthorized', {
legacyCode: 'unauthorized',
});
}
const normalizedFileMetadata = options?.pathAlreadyNormalized
? fileMetadata
: this.#normalizeFileMetadataPath(req, fileMetadata);
if (!normalizedFileMetadata) {
throw new HttpError(400, 'Missing path', {
legacyCode: 'bad_request',
});
}
const targetPath = normalizedFileMetadata.path;
if (targetPath === '/') {
throw new HttpError(400, 'Cannot write to root path', {
legacyCode: 'cannot_write_to_root',
});
}
const parentPath = pathPosix.dirname(targetPath);
if (parentPath === '/') {
throw new HttpError(400, 'Cannot write to root path', {
legacyCode: 'cannot_write_to_root',
});
}
let pathToCheck = parentPath;
if (Boolean(normalizedFileMetadata.overwrite)) {
const destinationExists =
await this.services.fs.entryExistsByPath(targetPath);
if (destinationExists) {
pathToCheck = targetPath;
}
}View on GitHub (pinned to 908ec23eda)
Solutions
- Write to a concrete folder under the user's home, e.g. `/<username>/file.txt`.
- Validate the resolved path is not '/' before sending; if it is, prompt the user for a real destination.
- Audit the path-building logic — a root result almost always means an empty basename upstream.
- For batch writes, filter or reject '/' items before submission.
Example fix
// before
{ path: '/' + (name || '') } // collapses to '/' when name empty
// after
if (!name) throw new Error('name required');
{ path: `/${username}/${name}` } Defensive patterns
Strategy: validation
Validate before calling
function assertNotRoot(path) {
if (path === '/') throw new Error('Cannot write to root — choose a subfolder');
return path;
} Prevention
- Reject '/' destinations in the UI before submit.
- Audit path-join logic — a '/' result usually means an empty basename.
- Default to a concrete user folder for saves.
When it happens
Trigger: POST /write with `path: '/'`; a signWrite or batchWrite item whose path normalizes to `/`; a client that builds the path from a dirname that collapses to root (e.g. basename empty).
Common situations: Frontend letting the user save to the literal root; a path-join bug where dirname swallows the filename; default path constant set to '/'; copy/move destination computed as root.
Related errors
- bad_request
- bad_request
- ${key} must be an integer between ${min} and ${max}
- bad_request
- password_required
AI-assisted analysis of HeyPuter/puter@908ec23eda (2026-08-12).
Data as JSON: /api/errors/d07d918445131d56.
Report an issue: GitHub.