HeyPuter/puter · error · HttpError

cannot_write_to_root

cannot_write_to_root

Error message

Cannot write to root path

What it means

In #assertWriteAccess, if the fully resolved puter_output_path is exactly '/', the driver refuses to write with HTTP 400 cannot_write_to_root. Writing the generated image over the filesystem root is forbidden.

Source

Thrown at src/backend/drivers/ai-image/ImageGenerationDriver.ts:446

        if (resolved === '~' || resolved.startsWith('~/')) {
            resolved = `/${username}${resolved.slice(1)}`;
        }
        assertNormalized(resolved);
        if (!resolved.startsWith('/')) {
            resolved = `/${resolved}`;
        }
        if (resolved.length > 1 && resolved.endsWith('/')) {
            resolved = resolved.slice(0, -1);
        }
        return resolved;
    }

    async #assertWriteAccess(
        actor: Actor,
        resolvedPath: string,
    ): Promise<void> {
        if (resolvedPath === '/') {
            throw new HttpError(400, 'Cannot write to root path', {
                legacyCode: 'cannot_write_to_root',
            });
        }
        const parentPath = pathPosix.dirname(resolvedPath);
        if (parentPath === '/') {
            throw new HttpError(400, 'Cannot write to root path', {
                legacyCode: 'cannot_write_to_root',
            });
        }

        const pathToCheck = parentPath;
        const fsService = this.services.fs;
        let ancestorsCache: Promise<
            Array<{ uid: string; path: string }>
        > | null = null;
        const canWrite = await this.services.acl.check(
            actor,
            {

View on GitHub (pinned to 908ec23eda)

Solutions

  1. Pass a concrete file path like '/Pictures/gen.png', never '/' or empty.
  2. Validate puter_output_path is a non-root file path before calling generate().

Example fix

// before
await driver.generate({ prompt, puter_output_path: '/' });
// after
await driver.generate({ prompt, puter_output_path: '/Pictures/gen.png' });
Defensive patterns

Strategy: validation

Validate before calling

const posix = require('node:path').posix;
const norm = posix.normalize(puter_outputPath);
if (norm === '/') throw new Error('cannot write generated image to root');

Type guard

function isNonRootFilePath(p) {
  const n = require('node:path').posix.normalize(p ?? '');
  return typeof p === 'string' && n !== '/' && n.trim() !== '';
}

Prevention

When it happens

Trigger: Caller passes puter_output_path that normalizes to '/' — e.g. '/', an empty string after normalization, or a path that collapses to root.

Common situations: Passing puter_output_path: '/' or '' by mistake; a path-templating bug that produces an empty/root path; UI default that accidentally resolves to root.

Related errors


AI-assisted analysis of HeyPuter/puter@908ec23eda (2026-08-12). Data as JSON: /api/errors/5f570f9124ef1ecc. Report an issue: GitHub.