HeyPuter/puter · warning · HttpError

bad_request

bad_request

Error message

Cannot GET a directory

What it means

Returned (HTTP 400, legacy code bad_request) by WebDAVController.#get when the resolved entry is a directory. HTTP GET on a directory is not supported here — directories must be accessed via PROPFIND (Depth header) instead. The existence check passes but isDir is true.

Source

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

                'Cache-Control': 'no-cache',
            })
            .send('');
    }

    // -- GET / HEAD --------------------------------------------------

    async #get(
        req: Request,
        res: Response,
        actor: Actor,
        davPath: string,
        headOnly: boolean,
    ): Promise<void> {
        const entry = await this.stores.fsEntry.getEntryByPath(davPath);
        if (!entry)
            throw new HttpError(404, 'Not Found', { legacyCode: 'not_found' });
        if (entry.isDir)
            throw new HttpError(400, 'Cannot GET a directory', {
                legacyCode: 'bad_request',
            });

        await this.#assertRead(actor, davPath);

        const etag = `"${entry.uuid}-${Math.floor(entry.modified ?? entry.created ?? 0)}"`;
        const size = entry.size ?? 0;

        res.set({
            'Accept-Ranges': 'bytes',
            'Content-Length': String(size),
            'Last-Modified': new Date(
                entry.modified ?? entry.created ?? 0,
            ).toUTCString(),
            ETag: etag,
        });

        if (headOnly) {

View on GitHub (pinned to 908ec23eda)

Solutions

  1. Use PROPFIND with a Depth header to list directory contents.
  2. Target a specific file path with GET, not a folder.
  3. Configure the WebDAV client to treat collections as PROPFIND targets.
Defensive patterns

Strategy: type-guard

Validate before calling

// Use PROPFIND for directories, GET only for files
const isDirPath = (p) => p.endsWith('/');
const method = isDirPath(path) ? 'PROPFIND' : 'GET';

Try / catch

try { await davGet(path); }
catch (e) { if (e.status === 400 && /directory/i.test(e.message)) await davPropfind(path); else throw e; }

Prevention

When it happens

Trigger: Issuing a WebDAV GET against a folder path (e.g. the mount root '/' or any collection). A client that tries to download a directory as if it were a file.

Common situations: Mounting a WebDAV drive and the client's initial GET hits the root; pointing a file-downloader at a folder URL; GUI dragging a folder to a GET-only downloader.

Related errors


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