can1357/oh-my-pi · error
No local TTS model registered for key: ${modelKey ?? DEFAULT
Error message
No local TTS model registered for key: ${modelKey ?? DEFAULT_TTS_LOCAL_MODEL_KEY} What it means
resolveTtsRepo maps a local TTS model key to its Hugging Face repo id. The key is looked up in the registered model spec table, falling back to the default key ("kokoro"); if neither the given key nor the default resolves to a spec, it throws. In practice this means the caller passed an unknown model key AND the default spec table is empty/missing the default entry.
Source
Thrown at packages/coding-agent/src/tts/models.ts:122
value: voice.id,
label: voice.label,
})) as ReadonlyArray<{ value: string; label: string }>;
/** Accepted `tts.localVoice` values (default model's catalog) for schema validation. */
export const TTS_LOCAL_VOICE_VALUES = KOKORO_VOICES.map(voice => voice.id) as readonly string[];
export function getTtsLocalModelSpec(key: string): TtsLocalModelSpec | undefined {
return TTS_LOCAL_MODELS.find(model => model.key === key);
}
export function isTtsLocalModelKey(value: string): value is TtsLocalModelKey {
return getTtsLocalModelSpec(value) !== undefined;
}
/** Resolve a model key (or the default) to its Hugging Face repo id. */
export function resolveTtsRepo(modelKey: string | undefined): string {
const spec = (modelKey && getTtsLocalModelSpec(modelKey)) || getTtsLocalModelSpec(DEFAULT_TTS_LOCAL_MODEL_KEY);
if (!spec) throw new Error(`No local TTS model registered for key: ${modelKey ?? DEFAULT_TTS_LOCAL_MODEL_KEY}`);
return spec.repo;
}
/**
* Resolve a requested voice id to a concrete voice the model supports, falling
* back to the model's default voice (first entry) when the id is unknown or the
* legacy `"default"` sentinel. The returned id is always a valid Kokoro voice.
*/
export function resolveTtsVoice(modelKey: string | undefined, voice: string | undefined): string {
const spec = (modelKey && getTtsLocalModelSpec(modelKey)) || getTtsLocalModelSpec(DEFAULT_TTS_LOCAL_MODEL_KEY);
const fallback = spec?.voices[0]?.id ?? DEFAULT_TTS_VOICE;
if (!spec || !voice) return fallback;
const match = spec.voices.find(v => v.id === voice);
return match ? match.id : fallback;
}
View on GitHub (pinned to 9690622007)
Solutions
- Use a registered model key (e.g. "kokoro") or unset the config so the default applies
- List available keys via the local model spec table (isTtsLocalModel / getTtsLocalModelSpec) and pick a valid one
- Check for renames after upgrading — update the tts.localModel setting to the new key
- If even the default fails, verify the models.ts spec table is intact (build/registration issue)
Example fix
// before
resolveTtsRepo("kokoro-82m-v1"); // unknown key
// after
resolveTtsRepo("kokoro"); // registered key (or undefined for default) Defensive patterns
Strategy: fallback
Validate before calling
import { isTtsLocalModelKey } from './models';
const key = isTtsLocalModelKey(config.tts.localModel) ? config.tts.localModel : undefined; // undefined -> default Type guard
function isValidTtsModelKey(key) {
return typeof key === 'string' && isTtsLocalModelKey(key);
} Try / catch
let repo;
try {
repo = resolveTtsRepo(config.tts.localModel);
} catch (err) {
if (err.message.includes('No local TTS model registered')) {
repo = resolveTtsRepo(undefined); // fall back to default model
} else throw err;
} Prevention
- Validate tts.localModel against the registered key list at config load time
- Use undefined rather than a hand-typed string when you want the default model
- After upgrades, re-check for renamed model keys in release notes
When it happens
Trigger: Calling resolveTtsRepo("some-model") where "some-model" is not in the local model spec table and getTtsLocalModelSpec(DEFAULT_TTS_LOCAL_MODEL_KEY) also returns undefined; passing undefined relies entirely on the default spec existing.
Common situations: A config sets tts.localModel to a typo'd or renamed key; a build/registration bug leaves the spec table unpopulated; a version upgrade removed or renamed a model key still referenced in user settings.
Related errors
- Audio gain must be a finite non-negative number
- Unable to resolve ${KOKORO_PACKAGE} in runtime at ${nodeModu
- Unable to resolve ${TRANSFORMERS_PACKAGE} in runtime at ${no
- No model configured
- Azure OpenAI base URL is required. Set AZURE_OPENAI_BASE_URL
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/ce7de17681f5e615.
Report an issue: GitHub.