moeru-ai/airi · error · Error

Failed to fetch voices

Error message

Failed to fetch voices: ${response.statusText}

What it means

listVoices fetches voicesUrl(config) — an HTTP endpoint on the user's self-hosted Index-TTS vLLM deployment — and throws with statusText when the response is not OK. statusText is often empty on HTTP/2, so the message may carry little detail. The signature is: the host is reachable but this specific route is not available.

Solutions

  1. curl the voices URL from the same machine to see the actual status
  2. Fix the provider's baseURL (scheme, host, port, path) in settings
  3. Deploy a vLLM build that implements the IndexTTS voices route
  4. Ensure no auth header or proxy requirement blocks the endpoint

Example fix

// before
baseUrl: 'http://localhost' // wrong port → voices route 404

// after
baseUrl: 'http://localhost:8000' // verify with: curl http://localhost:8000/voices
Defensive patterns

Strategy: validation

Validate before calling

try {
  const probe = await fetch(voicesUrl(config), { method: 'HEAD' })
  if (!probe.ok) showConfigError('Voices endpoint not available — check baseURL')
}
catch {
  showConfigError('Cannot reach the vLLM server')
}

Try / catch

try {
  const voices = await provider.extraMethods.listVoices(config)
}
catch (err) {
  // Distinguish HTTP rejection (this error) from network refusal:
  // HTTP rejection means the deployment or path is wrong, not the network.
  toast('Voices endpoint rejected the request — verify baseURL and deployment')
}

Prevention

When it happens

Trigger: baseURL points at the wrong port or path so the voices route resolves to a 404; the deployed vLLM IndexTTS build does not expose a voices route; the endpoint requires auth and returns 401/403; a proxy in front returns 502.

Common situations: Local vLLM server not started or started without the IndexTTS routes; base URL copied from a different project with another path prefix; corporate proxy intercepting the endpoint.

Related errors


AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18). Data as JSON: /api/errors/c8dae209887c9c71. Report an issue: GitHub.

Appendix: 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 677329427f)