SillyTavern/SillyTavern · error
Internal Server Error
Error message
Internal Server Error
What it means
HTTP 500 from POST /api/horde/text-workers in src/endpoints/horde.js:77. The handler fetches https://aihorde.net/api/v2/workers?type=text via node-fetch and returns the JSON; any rejection (DNS failure, connection refused, TCP reset, response.json() parse error) lands in the catch and sendStatus(500) is emitted. There is no retry or fallback.
Source
Thrown at src/endpoints/horde.js:77
try {
const cachedWorkers = cache.get('workers');
if (cachedWorkers && !request.body.force) {
return response.send(cachedWorkers);
}
const agent = await getClientAgent();
const fetchResult = await fetch('https://aihorde.net/api/v2/workers?type=text', {
headers: {
'Client-Agent': agent,
},
});
const data = await fetchResult.json();
cache.set('workers', data);
return response.send(data);
} catch (error) {
console.error(error);
response.sendStatus(500);
}
});
async function getHordeTextModelMetadata() {
const response = await fetch(HORDE_TEXT_MODEL_METADATA_URL);
return await response.json();
}
async function mergeModelsAndMetadata(models, metadata) {
return models.map(model => {
const metadataModel = metadata[model.name];
if (!metadataModel) {
return { ...model, is_whitelisted: false };
}
return { ...model, ...metadataModel, is_whitelisted: true };
});
}
View on GitHub (pinned to 8172dcd0ee)
Solutions
- Verify outbound HTTPS to https://aihorde.net/api/v2/workers?type=text works from the host (curl -I).
- If behind a proxy, set HTTPS_PROXY/HTTP_PROXY and ensure node-fetch honors it, or whitelist aihorde.net.
- Wait and retry: the error is often transient and the 60s cache will serve stale data on the next non-forced call.
- Check server console logs (console.error(error)) for the underlying node-fetch error code (ENOTFOUND, ECONNRESET, ETIMEDOUT) to pinpoint DNS vs network vs TLS.
Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight reachability hint (optional)
async function hordeReachable() {
try {
const r = await fetch('https://aihorde.net/api/v2/status/heartbeat', { method:'HEAD' });
return r.ok;
} catch { return false; }
} Try / catch
// Caller: retry transient horde worker fetch failures
async function getTextWorkers(maxAttempts = 3) {
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
const r = await fetch('/api/horde/text-workers', { method:'POST', headers:{'Content-Type':'application/json'}, body:'{}' });
if (r.ok) return await r.json();
if (r.status === 500 && attempt < maxAttempts) { await new Date(); continue; }
throw new Error('text-workers failed: ' + r.status);
} catch (e) {
if (attempt === maxAttempts) throw e;
}
}
} Prevention
- Rely on the server cache by not forcing refresh unless necessary.
- Monitor aihorde.net status; treat 500 as transient before alerting.
- Ensure outbound HTTPS to aihorde.net is permitted by firewall/proxy.
When it happens
Trigger: The server has no internet route to aihorde.net; a corporate proxy/firewall blocks the host; aihorde.net is down or returns non-JSON (HTML error page) so fetchResult.json() throws; getClientAgent() throws because getVersion() fails; cache miss with request.body.force=true forcing a live fetch during an outage.
Common situations: Running SillyTavern behind a restrictive firewall or in an offline/air-gapped environment; DNS hiccup; the user clicked 'refresh/force' which bypasses the 60s cache; node-fetch version mismatch causing undici/Headers issues; a transient aihorde.net 5xx that still serves JSON but the connection drops mid-stream.
Understand the failure class
- HTTP status errors: handling 4xx and 5xx responses — how to handle 4xx and 5xx responses properly.
Related errors
- Unexpected response ${res.statusText}
- Internal Server Error
- An unknown network error occurred.
- Failed to connect to the Azure endpoint.
- Bad Request
AI-assisted analysis of SillyTavern/SillyTavern@8172dcd0ee (2026-08-13).
Data as JSON: /api/errors/1069a4440eb19fee.
Report an issue: GitHub.