SillyTavern/SillyTavern · error

Internal Server Error

Error message

Internal Server Error

What it means

Generic 500 returned by the catch block of POST /api/secrets/write when SecretManager.writeSecret throws. writeSecret reads secrets.json, JSON.parses it, deactivates existing entries, pushes the new secret, then atomically rewrites the file via write-file-atomic. Any failure in that chain (corrupted JSON, unreadable/unwritable file, disk full during the atomic temp-file swap) bubbles up here.

Source

Thrown at src/endpoints/secrets.js:525

}

export const router = express.Router();

router.post('/write', (request, response) => {
    try {
        const { key, value, label } = request.body;

        if (!key || typeof value !== 'string') {
            return response.status(400).send('Invalid key or value');
        }

        const manager = new SecretManager(request.user.directories);
        const id = manager.writeSecret(key, value, label);

        return response.send({ id });
    } catch (error) {
        console.error('Error writing secret:', error);
        return response.sendStatus(500);
    }
});

router.post('/read', (request, response) => {
    try {
        const manager = new SecretManager(request.user.directories);
        const state = manager.getSecretState();
        return response.send(state);
    } catch (error) {
        console.error('Error reading secret state:', error);
        return response.send({});
    }
});

router.post('/view', (request, response) => {
    try {
        if (!allowKeysExposure) {
            console.error('secrets.json could not be viewed unless allowKeysExposure in config.yaml is set to true');

View on GitHub (pinned to 8172dcd0ee)

Solutions

  1. Read the server console output: the line 'Error writing secret:' prints the underlying Error (ENOENT, EACCES, SyntaxError, ENOSPC).
  2. If SyntaxError: open data/<user>/secrets.json and validate/repair the JSON, or restore from data/<user>/backups/secrets_migration_*.json.
  3. If EACCES/EROFS: fix ownership/permissions on the user root directory (chmod/chown) or remount the data volume read-write.
  4. If unrecoverable: back up then delete secrets.json; SecretManager._ensureSecretsFile recreates an empty one on next access.

Example fix

// before: corrupted secrets.json breaks every write
// after: validate and self-heal on startup
import { SecretManager } from './src/endpoints/secrets.js';
try {
  new SecretManager(user.directories)._readSecretsFile();
} catch (e) {
  fs.copyFileSync(secretsPath, `${secretsPath}.broken-${Date.now()}`);
  fs.rmSync(secretsPath, { force: true }); // recreated empty on next write
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Before calling /api/secrets/write, sanity-check the target file is parseable
const fs = require('node:fs');
function canWriteSecrets(rootDir) {
  const p = require('node:path').join(rootDir, 'secrets.json');
  if (!fs.existsSync(p)) return true; // will be auto-created
  try { JSON.parse(fs.readFileSync(p, 'utf8')); return true; }
  catch { return false; }
}

Type guard

/** @param {any} b */
function isValidWriteBody(b) {
  return !!b && typeof b === 'object'
    && typeof b.key === 'string' && b.key.length > 0
    && typeof b.value === 'string';
}

Try / catch

try {
  const r = await fetch('/api/secrets/write', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ key, value, label }) });
  if (r.status === 500) throw new Error('secret store unavailable — check secrets.json');
  return await r.json();
} catch (e) { showUser('Could not save secret: ' + e.message); }

Prevention

When it happens

Trigger: POST /api/secrets/write with a valid key/value but where secrets.json is malformed JSON, where the user's root directory is not writable, where the disk is full, or where an external process (antivirus, indexer) holds an exclusive lock on secrets.json during the atomic write.

Common situations: User hand-edited data/<user>/secrets.json and introduced a syntax error; a partial write from a crashed server left truncated JSON; data directory moved onto a read-only mount; container mounted data volume read-only; Windows Defender locking the file during write.

Understand the failure class

Related errors


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