SillyTavern/SillyTavern · warning

Error: no avatar_url in request body

Error message

Error: no avatar_url in request body

What it means

POST /api/characters/edit-avatar needs request.body.avatar_url to know which existing character's embedded data should be transplanted onto the new image (src/endpoints/characters.js:1146). If the body is missing or lacks avatar_url, the handler returns 400 'Error: no avatar_url in request body'.

Source

Thrown at src/endpoints/characters.js:1147

            // Bust cache to reload the new avatar
            cacheBuster.bust(request, response);
        }

        return response.sendStatus(200);
    } catch (err) {
        console.error('An error occurred, character edit invalidated.', err);
        return response.sendStatus(500);
    }
});

router.post('/edit-avatar', validateAvatarUrlMiddleware, async function (request, response) {
    try {
        if (!request.file) {
            return response.status(400).send('Error: no file uploaded');
        }

        if (!request.body || !request.body.avatar_url) {
            return response.status(400).send('Error: no avatar_url in request body');
        }

        const uploadPath = path.join(request.file.destination, request.file.filename);
        if (!fs.existsSync(uploadPath)) {
            return response.status(400).send('Error: uploaded file does not exist');
        }
        const characterPath = path.join(request.user.directories.characters, request.body.avatar_url);
        if (!fs.existsSync(characterPath)) {
            return response.status(400).send('Error: character file does not exist');
        }
        const data = await readCharacterData(characterPath);
        if (!data) {
            return response.status(400).send('Error: failed to read character data');
        }

        const crop = tryParse(request.query.crop);
        const fileName = request.body.avatar_url.replace('.png', '');
        await writeCharacterData(uploadPath, data, fileName, request, crop);

View on GitHub (pinned to 8172dcd0ee)

Solutions

  1. Append avatar_url as a multipart text field referencing an existing <name>.png character file.
  2. Ensure the character was created first via /create before calling /edit-avatar.
  3. Refresh the character list and use a current avatar_url value.

Example fix

// before
const fd = new FormData();
fd.append('avatar', file);
// after
const fd = new FormData();
fd.append('avatar', file);
fd.append('avatar_url', 'Aiko.png');
Defensive patterns

Strategy: validation

Validate before calling

const fd = new FormData();
fd.append('avatar', file, file.name);
if (!avatarUrl) throw new Error('avatar_url is required');
fd.append('avatar_url', avatarUrl);

Type guard

const hasAvatarUrl = (s) => typeof s === 'string' && s.length > 0 && s.endsWith('.png');

Prevention

When it happens

Trigger: Multipart form submitted with only a file and no avatar_url text field; avatar_url field left empty; body entirely empty.

Common situations: Frontend forgot to include the avatar_url form field alongside the file; user tried to edit an avatar for a character that was never saved.

Related errors


AI-assisted analysis of SillyTavern/SillyTavern@8172dcd0ee (2026-08-13). Data as JSON: /api/errors/7abd2f316e8ea5c7. Report an issue: GitHub.