{"record":{"id":"6894313b119e85c6","repo":"SillyTavern/SillyTavern","slug":"no-path-specified-689431","errorCode":null,"errorMessage":"No path specified","messagePattern":"No path specified","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"src/endpoints/images.js","lineNumber":136,"sourceCode":"        if (!fs.existsSync(directoryPath)) {\n            fs.mkdirSync(directoryPath, { recursive: true });\n        }\n\n        const folders = fs.readdirSync(directoryPath, { withFileTypes: true })\n            .filter(dirent => dirent.isDirectory())\n            .map(dirent => dirent.name);\n\n        return response.send(folders);\n    } catch (error) {\n        console.error(error);\n        return response.status(500).send({ error: 'Unable to retrieve folders' });\n    }\n});\n\nrouter.post('/delete', async (request, response) => {\n    try {\n        if (!request.body.path) {\n            return response.status(400).send('No path specified');\n        }\n\n        const pathToDelete = path.join(request.user.directories.root, request.body.path);\n        if (!isPathUnderParent(request.user.directories.userImages, pathToDelete)) {\n            return response.status(400).send('Invalid path');\n        }\n\n        if (!fs.existsSync(pathToDelete)) {\n            return response.status(404).send('File not found');\n        }\n\n        fs.unlinkSync(pathToDelete);\n        console.info(`Deleted image: ${request.body.path} from ${request.user.profile.handle}`);\n        return response.sendStatus(200);\n    } catch (error) {\n        console.error(error);\n        return response.sendStatus(500);\n    }","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/SillyTavern/SillyTavern/blob/8172dcd0ee672d3cd9a5e5f7af134f91a45cd2b8/src/endpoints/images.js#L118-L154","documentation":"400 validation failure in POST /api/images/delete. The handler requires request.body.path to be truthy before it will resolve or delete anything. Sending no path field, an empty string, or null short-circuits here. This is a client-contract error, not a server fault.","triggerScenarios":"POST /api/images/delete with an empty body, a body where `path` is omitted, set to '', null, or 0. Typically a client that forgot to attach the selected file's path, or a deserialization bug that drops the field.","commonSituations":"Frontend bug that sends the delete request before populating the path; JSON.stringify of an undefined value yielding an empty object; a bulk-delete refactor that no longer threads the per-item path through.","solutions":["On the client, confirm the selected image's relative path is attached as `path` in the JSON body before firing the request.","Add a client-side guard that disables the delete button until a path is selected, preventing the empty-body request entirely.","Inspect the outgoing request payload in the browser network tab to confirm `path` is present and non-empty."],"exampleFix":"// before: fires regardless of selection\ndeleteImage();\n\n// after: guard before sending\nif (!selectedImagePath) { return; }\nawait fetch('/api/images/delete', {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/json' },\n    body: JSON.stringify({ path: selectedImagePath }),\n});","handlingStrategy":"validation","validationCode":"// Client-side: never send the delete request without a path\nfunction buildDeleteBody(path) {\n  if (typeof path !== 'string' || path.trim().length === 0) {\n    throw new Error('path is required and must be a non-empty string');\n  }\n  return JSON.stringify({ path });\n}","typeGuard":"/** @param {unknown} p @returns {p is string} */\nfunction isNonEmptyPath(p) {\n  return typeof p === 'string' && p.trim().length > 0;\n}","tryCatchPattern":null,"preventionTips":["Disable the delete control until a path is selected.","Use the exact path string returned by /list or /upload; do not synthesize it.","Add a unit test that the client always attaches `path` to delete requests.","Validate with a shared schema (e.g. zod) on both client and server."],"tags":["validation","api","client-error","express"],"backgroundTag":null,"analyzedSha":"8172dcd0ee672d3cd9a5e5f7af134f91a45cd2b8","analyzedAt":"2026-08-13T07:48:40.832Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}