{"record":{"id":"ed386115f374d25c","repo":"SillyTavern/SillyTavern","slug":"internal-server-error-ed3861","errorCode":null,"errorMessage":"Internal Server Error","messagePattern":"Internal Server Error","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"src/endpoints/worldinfo.js","lineNumber":67,"sourceCode":"                const fileContents = await fs.promises.readFile(filePath, 'utf8');\n                const fileContentsParsed = tryParse(fileContents) || {};\n                const fileExtensions = fileContentsParsed?.extensions || {};\n                const fileNameWithoutExt = path.parse(file.name).name;\n                const fileData = {\n                    file_id: fileNameWithoutExt,\n                    name: fileContentsParsed?.name || fileNameWithoutExt,\n                    extensions: _.isObjectLike(fileExtensions) ? fileExtensions : {},\n                };\n                data.push(fileData);\n            } catch (err) {\n                console.warn(`Error reading or parsing World Info file ${file.name}:`, err);\n            }\n        }\n\n        return response.send(data);\n    } catch (err) {\n        console.error('Error reading World Info directory:', err);\n        return response.sendStatus(500);\n    }\n});\n\nrouter.post('/get', (request, response) => {\n    if (!request.body?.name) {\n        return response.sendStatus(400);\n    }\n\n    const file = readWorldInfoFile(request.user.directories, request.body.name, true);\n\n    return response.send(file);\n});\n\nrouter.post('/delete', (request, response) => {\n    if (!request.body?.name) {\n        return response.sendStatus(400);\n    }\n","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/SillyTavern/SillyTavern/blob/8172dcd0ee672d3cd9a5e5f7af134f91a45cd2b8/src/endpoints/worldinfo.js#L49-L85","documentation":"HTTP 500 from the World Info list/index route's catch block. The handler reads and parses every JSON file in the user's worlds directory; any unexpected error (typically a FS-level failure reading the directory itself) is logged and returned as a generic 500.","triggerScenarios":"fs.readdir or stat on `request.user.directories.worlds` throws (ENOENT if the worlds dir does not exist, EACCES on permission denied), or another low-level FS error occurs before per-file parsing. Individual file parse errors are swallowed (only warned), so a 500 implies the directory read itself failed.","commonSituations":"The worlds directory was deleted or never created for the user; data dir on an unmounted/read-only volume; server process lacks read permission on the worlds folder; symlink loop or broken symlink in the worlds path.","solutions":["Confirm `data/<user>/worlds` exists and is readable by the server process.","Check server log for `Error reading World Info directory:` to see the real errno.","Fix ownership/permissions on the data directory, or recreate the worlds folder.","If the volume is read-only or unmounted, remount/repair it and retry."],"exampleFix":"// before\n// (client just receives 500 with no detail)\n// after - ensure dir exists at startup\nfs.mkdirSync(path.join(userDir, 'worlds'), { recursive: true });","handlingStrategy":"try-catch","validationCode":"import fs from 'node:fs';\nfs.mkdirSync(path.join(userDir, 'worlds'), { recursive: true });\nawait fs.promises.access(path.join(userDir, 'worlds'), fs.constants.R_OK);","typeGuard":null,"tryCatchPattern":"try { /* read worlds dir */ } catch (err) { console.error('Error reading World Info directory:', err); if (err.code === 'ENOENT') { /* recreate and retry */ } else { response.sendStatus(500); } }","preventionTips":["Ensure the worlds directory exists at user creation time.","Keep the data dir on a writable volume.","Watch the log for the actual errno."],"tags":["worldinfo","filesystem","http-500","permissions"],"backgroundTag":null,"analyzedSha":"8172dcd0ee672d3cd9a5e5f7af134f91a45cd2b8","analyzedAt":"2026-08-13T07:48:40.832Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}