{"record":{"id":"e6bc17583fe776b6","repo":"HeyPuter/puter","slug":"bad-request-e6bc17","errorCode":"bad_request","errorMessage":"Cannot GET a directory","messagePattern":"Cannot GET a directory","errorType":"http","errorClass":"HttpError","httpStatus":400,"severity":"warning","filePath":"src/backend/controllers/webdav/WebDAVController.ts","lineNumber":360,"sourceCode":"                'Cache-Control': 'no-cache',\n            })\n            .send('');\n    }\n\n    // -- GET / HEAD --------------------------------------------------\n\n    async #get(\n        req: Request,\n        res: Response,\n        actor: Actor,\n        davPath: string,\n        headOnly: boolean,\n    ): Promise<void> {\n        const entry = await this.stores.fsEntry.getEntryByPath(davPath);\n        if (!entry)\n            throw new HttpError(404, 'Not Found', { legacyCode: 'not_found' });\n        if (entry.isDir)\n            throw new HttpError(400, 'Cannot GET a directory', {\n                legacyCode: 'bad_request',\n            });\n\n        await this.#assertRead(actor, davPath);\n\n        const etag = `\"${entry.uuid}-${Math.floor(entry.modified ?? entry.created ?? 0)}\"`;\n        const size = entry.size ?? 0;\n\n        res.set({\n            'Accept-Ranges': 'bytes',\n            'Content-Length': String(size),\n            'Last-Modified': new Date(\n                entry.modified ?? entry.created ?? 0,\n            ).toUTCString(),\n            ETag: etag,\n        });\n\n        if (headOnly) {","sourceCodeStart":342,"sourceCodeEnd":378,"githubUrl":"https://github.com/HeyPuter/puter/blob/908ec23eda38526170322c3edf71ba45ecb1ca95/src/backend/controllers/webdav/WebDAVController.ts#L342-L378","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Use PROPFIND with a Depth header to list directory contents.","Target a specific file path with GET, not a folder.","Configure the WebDAV client to treat collections as PROPFIND targets."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"// Use PROPFIND for directories, GET only for files\nconst isDirPath = (p) => p.endsWith('/');\nconst method = isDirPath(path) ? 'PROPFIND' : 'GET';","typeGuard":null,"tryCatchPattern":"try { await davGet(path); }\ncatch (e) { if (e.status === 400 && /directory/i.test(e.message)) await davPropfind(path); else throw e; }","preventionTips":["Route collection paths to PROPFIND.","Configure the WebDAV client to PROPFIND on folders.","Check entry metadata (isDir) before choosing the verb."],"tags":["webdav","filesystem","bad-request","is-dir"],"backgroundTag":null,"analyzedSha":"908ec23eda38526170322c3edf71ba45ecb1ca95","analyzedAt":"2026-08-12T20:53:15.911Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}