From 84383b5e0f7229c8352a8d3063d00138f0a1e7b7 Mon Sep 17 00:00:00 2001 From: ikari Date: Mon, 16 Feb 2026 11:29:31 +0100 Subject: [PATCH] fix(tts): show all provider errors instead of only the last one When TTS conversion fails, the error message now includes failures from every provider in the fallback chain instead of only the last one tried. Previously, a timeout on the primary provider (e.g. ElevenLabs) would be masked by the final fallback's error (e.g. "edge: disabled"), making it impossible to diagnose the real issue. Before: "TTS conversion failed: edge: disabled" After: "TTS conversion failed: elevenlabs: timeout (30004ms); openai: no API key; edge: disabled" --- src/tts/tts.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/tts/tts.ts b/src/tts/tts.ts index 8a2200dff32..edfa8eda62e 100644 --- a/src/tts/tts.ts +++ b/src/tts/tts.ts @@ -551,14 +551,14 @@ export async function textToSpeech(params: { const provider = overrideProvider ?? userProvider; const providers = resolveTtsProviderOrder(provider); - let lastError: string | undefined; + const errors: string[] = []; for (const provider of providers) { const providerStart = Date.now(); try { if (provider === "edge") { if (!config.edge.enabled) { - lastError = "edge: disabled"; + errors.push("edge: disabled"); continue; } @@ -626,7 +626,7 @@ export async function textToSpeech(params: { const apiKey = resolveTtsApiKey(config, provider); if (!apiKey) { - lastError = `No API key for ${provider}`; + errors.push(`${provider}: no API key`); continue; } @@ -683,13 +683,13 @@ export async function textToSpeech(params: { voiceCompatible: output.voiceCompatible, }; } catch (err) { - lastError = formatTtsProviderError(provider, err); + errors.push(formatTtsProviderError(provider, err)); } } return { success: false, - error: `TTS conversion failed: ${lastError || "no providers available"}`, + error: `TTS conversion failed: ${errors.join("; ") || "no providers available"}`, }; } @@ -711,19 +711,19 @@ export async function textToSpeechTelephony(params: { const userProvider = getTtsProvider(config, prefsPath); const providers = resolveTtsProviderOrder(userProvider); - let lastError: string | undefined; + const errors: string[] = []; for (const provider of providers) { const providerStart = Date.now(); try { if (provider === "edge") { - lastError = "edge: unsupported for telephony"; + errors.push("edge: unsupported for telephony"); continue; } const apiKey = resolveTtsApiKey(config, provider); if (!apiKey) { - lastError = `No API key for ${provider}`; + errors.push(`${provider}: no API key`); continue; } @@ -772,13 +772,13 @@ export async function textToSpeechTelephony(params: { sampleRate: output.sampleRate, }; } catch (err) { - lastError = formatTtsProviderError(provider, err); + errors.push(formatTtsProviderError(provider, err)); } } return { success: false, - error: `TTS conversion failed: ${lastError || "no providers available"}`, + error: `TTS conversion failed: ${errors.join("; ") || "no providers available"}`, }; }