{"record":{"id":"dd4199763a918a8d","repo":"SillyTavern/SillyTavern","slug":"not-found-dd4199","errorCode":null,"errorMessage":"Not Found","messagePattern":"Not Found","errorType":"http","errorClass":null,"httpStatus":404,"severity":"warning","filePath":"src/endpoints/characters.js","lineNumber":1485,"sourceCode":"        const pngFiles = files.filter(file => file.endsWith('.png'));\n        const processingPromises = pngFiles.map(file => processCharacter(file, request.user.directories, { shallow: useShallowCharacters }));\n        const data = (await Promise.all(processingPromises)).filter(c => c.name);\n        return response.send(data);\n    } catch (err) {\n        console.error(err);\n        const isRangeError = err instanceof RangeError;\n        response.status(500).send({ overflow: isRangeError, error: true });\n    }\n});\n\nrouter.post('/get', validateAvatarUrlMiddleware, async function (request, response) {\n    try {\n        if (!request.body) return response.sendStatus(400);\n        const item = request.body.avatar_url;\n        const filePath = path.join(request.user.directories.characters, item);\n\n        if (!fs.existsSync(filePath)) {\n            return response.sendStatus(404);\n        }\n\n        const data = await processCharacter(item, request.user.directories, { shallow: false });\n\n        return response.send(data);\n    } catch (err) {\n        console.error(err);\n        response.sendStatus(500);\n    }\n});\n\nrouter.post('/chats', validateAvatarUrlMiddleware, async function (request, response) {\n    try {\n        if (!request.body) return response.sendStatus(400);\n\n        const characterDirectory = (request.body.avatar_url).replace('.png', '');\n        const chatsDirectory = path.join(request.user.directories.chats, characterDirectory);\n","sourceCodeStart":1467,"sourceCodeEnd":1503,"githubUrl":"https://github.com/SillyTavern/SillyTavern/blob/8172dcd0ee672d3cd9a5e5f7af134f91a45cd2b8/src/endpoints/characters.js#L1467-L1503","documentation":"HTTP 404 returned by POST /api/characters/get when the character .png file referenced by avatar_url does not exist in the user's characters directory. The server constructs the full path via path.join and checks fs.existsSync before calling processCharacter.","triggerScenarios":"POST /api/characters/get with an avatar_url for a character that was deleted, renamed, or never existed on this server instance.","commonSituations":"Stale client cache referencing a deleted character; avatar_url typo or truncation; cross-environment mismatch (dev vs production character sets).","solutions":["Refresh the character list via /api/characters/all to get current avatar_url values.","Handle the 404 in the client by removing the stale character from the UI.","Verify avatar_url matches an entry from the character list before requesting it."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Check character existence before fetching details\nasync function getCharacterSafely(avatar_url) {\n  const resp = await fetch('/api/characters/get', {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/json' },\n    body: JSON.stringify({ avatar_url }),\n  });\n  if (resp.status === 404) {\n    console.warn(`Character ${avatar_url} not found, may have been deleted`);\n    return null;\n  }\n  return resp.json();\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Refresh the character list periodically to keep avatar_url values current.","Handle 404 gracefully by removing the character from the client UI.","Never hard-code avatar_url values — always derive them from the /all endpoint."],"tags":["express","filesystem","validation","character-management"],"backgroundTag":null,"analyzedSha":"8172dcd0ee672d3cd9a5e5f7af134f91a45cd2b8","analyzedAt":"2026-08-13T07:48:40.832Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}