HeyPuter/puter · error · HttpError

forbidden

forbidden

Error message

Cannot create at root

What it means

Returned (HTTP 403, legacy code forbidden) by WebDAVController.#mkcol when davPath is '/' — i.e. MKCOL against the filesystem root. The root collection already exists and cannot be created; the server refuses rather than returning a generic 'already exists'.

Source

Thrown at src/backend/controllers/webdav/WebDAVController.ts:479

        res.status(207)
            .set({ 'Content-Type': 'application/xml; charset=utf-8' })
            .send(
                `<?xml version="1.0" encoding="utf-8"?>\n<D:multistatus xmlns:D="DAV:"><D:response><D:href>${escapeXml(encodeURI(davPath))}</D:href><D:propstat><D:prop/><D:status>HTTP/1.1 200 OK</D:status></D:propstat></D:response></D:multistatus>`,
            );
    }

    // -- MKCOL -------------------------------------------------------

    async #mkcol(
        req: Request,
        res: Response,
        actor: Actor,
        davPath: string,
        redis: unknown,
        lockToken: string | null,
    ): Promise<void> {
        if (davPath === '/')
            throw new HttpError(403, 'Cannot create at root', {
                legacyCode: 'forbidden',
            });
        if (
            req.headers['content-length'] &&
            Number(req.headers['content-length']) > 0
        ) {
            throw new HttpError(415, 'MKCOL must not have a body', {
                legacyCode: 'bad_request',
            });
        }
        if (
            !(await hasWritePermission(
                redis as import('ioredis').Cluster,
                davPath,
                lockToken,
            ))
        ) {
            throw new HttpError(423, 'Locked', { legacyCode: 'conflict' });

View on GitHub (pinned to 908ec23eda)

Solutions

  1. MKCOL a named subfolder, e.g. /MyFolder, never '/'.
  2. Fix the client's base-path so requests target a child collection.
  3. Treat root as always-present; skip the MKCOL if the target is root.
Defensive patterns

Strategy: validation

Validate before calling

function assertMkcolTarget(p){ if (p === '/' || p === '') throw new Error('cannot MKCOL root; target a named subfolder'); }

Try / catch

try { await davMkcol(path); }
catch (e) { if (e.status === 403 && /root/i.test(e.message)) { path = path + 'Home/'; await davMkcol(path); } else throw e; }

Prevention

When it happens

Trigger: A WebDAV MKCOL request whose target is the mount root (the user's top-level directory). A misconfigured client that resolves all paths against '/' and issues MKCOL '/' on connect.

Common situations: WebDAV client boot sequence that creates a base folder and the base folder resolves to root; incorrect base-path configuration so the effective path collapses to '/'.

Related errors


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