moeru-ai/airi · error · Error
Failed to fetch voices: ${response.statusText}
Error message
Failed to fetch voices: ${response.statusText} What it means
Thrown by listVoices() in the IndexTTS vLLM provider when the GET to the voices endpoint returns non-2xx. The voices endpoint is `${baseUrl}audio/voices`; a non-ok response means the IndexTTS vLLM server is unreachable or the base URL is wrong. Only the HTTP statusText is included (no body parsing).
Source
Thrown at packages/stage-ui/src/libs/providers/providers/index-tts-vllm/index.ts:81
return { errors: [], reason: '', reasonKey: '', valid: true }
},
}),
],
},
extraMethods: {
listModels: async () => [{
id: 'IndexTTS-1.5',
name: 'IndexTTS-1.5',
provider: 'index-tts-vllm',
description: 'Default model for Index-TTS vLLM deployment',
contextLength: 0,
deprecated: false,
}],
listVoices: async (config) => {
const response = await fetch(voicesUrl(config))
if (!response.ok)
throw new Error(`Failed to fetch voices: ${response.statusText}`)
const voices = await response.json() as Record<string, unknown>
return Object.keys(voices).map(voice => ({
id: voice,
name: voice,
provider: 'index-tts-vllm',
languages: [{ code: 'cn', title: 'Chinese' }, { code: 'en', title: 'English' }],
}))
},
},
})
View on GitHub (pinned to 27111382b4)
Solutions
- Confirm the IndexTTS vLLM server is running and healthy at the configured baseUrl.
- Verify baseUrl is correct (default http://localhost:11996/tts/); adjust port/host to match the deployment.
- curl ${baseUrl}audio/voices directly to confirm the route exists and returns 200 before configuring the provider.
- If the deployed server lacks /audio/voices, upgrade the IndexTTS vLLM image or pick a version that exposes it.
Defensive patterns
Strategy: try-catch
Validate before calling
async function isIndexTtsVoicesReachable(baseUrl: string, signal?: AbortSignal): Promise<boolean> {
try {
const res = await fetch(`${baseUrl}audio/voices`, { signal })
return res.ok
}
catch {
return false
}
}
// before configuring the provider / calling listVoices:
if (!await isIndexTtsVoicesReachable(config.baseUrl)) {
// IndexTTS vLLM not reachable; do not call listVoices
} Type guard
null
Try / catch
try {
const voices = await providerIndexTtsVllm.extraMethods!.listVoices!(config)
}
catch (err) {
if (err instanceof Error && err.message.startsWith('Failed to fetch voices')) {
// check IndexTTS server health and baseUrl; the validator runs the same check at config time
}
else throw err
} Prevention
- Confirm the IndexTTS vLLM server is running at baseUrl before configuring the provider.
- Use the config validator (validateConfig) which already probes /audio/voices with a 5s timeout.
- Match the baseUrl port/host to the actual deployment (default http://localhost:11996/tts/).
When it happens
Trigger: fetch(voicesUrl(config)) returns non-ok. The IndexTTS vLLM server is not running, the baseUrl points at the wrong host/port/path, the /audio/voices route is absent in the deployed version, or the server returned an error status.
Common situations: IndexTTS vLLM container not started. baseUrl left at default http://localhost:11996/tts/ but the server runs elsewhere. Server version without the /audio/voices route. Port mismatch / firewall blocking localhost. CORS in browser.
Related errors
- Gemini TTS request failed: ${response.status} ${await respon
- No reachable private LAN address is available for the curren
- listAccounts failed
- unlinkAccount failed
- HTTP ${res.status}: ${await readErrorDetail(res)}
AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12).
Data as JSON: /api/errors/c8dae209887c9c71.
Report an issue: GitHub.