{"record":{"id":"7902c216fb8b6342","repo":"moeru-ai/airi","slug":"invalid-model-modelid-must-be-one-of-kokor","errorCode":null,"errorMessage":"Invalid model: ${modelId}. Must be one of: ${KOKORO_MODELS.map(item => item.id).join(', ')}","messagePattern":"Invalid model: (.+?)\\. Must be one of: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/stage-ui/src/libs/providers/providers/kokoro-local/index.ts","lineNumber":45,"sourceCode":"  'pt-br': { code: 'pt-BR', title: 'Portuguese (Brazil)' },\n}\n\nfunction getWebGpuState() {\n  const capabilities = getCachedWebGPUCapabilities()\n  return {\n    supported: capabilities?.supported ?? (typeof navigator !== 'undefined' && Boolean(navigator.gpu)),\n    fp16Supported: capabilities?.fp16Supported ?? false,\n  }\n}\n\nfunction getModel(modelId: string) {\n  return KOKORO_MODELS.find(model => model.id === modelId)\n}\n\nfunction assertModelSupported(modelId: string) {\n  const model = getModel(modelId)\n  if (!model)\n    throw new Error(`Invalid model: ${modelId}. Must be one of: ${KOKORO_MODELS.map(item => item.id).join(', ')}`)\n\n  if (model.platform === 'webgpu' && !getWebGpuState().supported)\n    throw new Error('WebGPU is required for this model but is not available in your browser')\n\n  return model\n}\n\nfunction progressInfo(progress: { file?: string, percent: number, loaded?: number, total?: number }): ProgressInfo {\n  return {\n    name: progress.file ?? '',\n    file: progress.file ?? '',\n    progress: progress.percent >= 0 ? progress.percent : 0,\n    status: 'progress',\n    loaded: progress.loaded ?? 0,\n    total: progress.total ?? 0,\n  }\n}\n","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/stage-ui/src/libs/providers/providers/kokoro-local/index.ts#L27-L63","documentation":"assertModelSupported looks modelId up in the static KOKORO_MODELS catalog and throws when it is absent, listing the valid ids in the message. The id typically comes from persisted settings or caller code, so this fires when a stored id no longer exists in the catalog shipped by the running code.","triggerScenarios":"A settings record persisted by an older app version references a model id that was renamed or removed; a hardcoded model string has a typo; the catalog changed ids between ONNX and WebGPU variants across releases.","commonSituations":"App update renamed model variants; importing settings from another machine; manually editing stored provider config.","solutions":["Use one of the ids listed in the error message — it enumerates the current catalog","Re-select the model in the provider settings UI so the current catalog id is persisted","Fall back to the first catalog entry when the persisted id is unknown","Add a settings migration step when model ids change between releases"],"exampleFix":"// before\nkokoro.speech('kokoro-82m-int8-q4', ...) // id no longer in KOKORO_MODELS\n\n// after\nconst modelId = KOKORO_MODELS.some(m => m.id === savedId) ? savedId : KOKORO_MODELS[0]!.id\nkokoro.speech(modelId, ...)","handlingStrategy":"validation","validationCode":"const isValid = KOKORO_MODELS.some(m => m.id === selectedModelId)\nif (!isValid)\n  selectedModelId = KOKORO_MODELS[0]!.id","typeGuard":"function isKokoroModelId(id: string): boolean {\n  return KOKORO_MODELS.some(m => m.id === id)\n}","tryCatchPattern":"try {\n  assertModelSupported(modelId)\n}\ncatch (err) {\n  if (err.message.startsWith('Invalid model:'))\n    modelId = KOKORO_MODELS[0]!.id // reset to a valid default and continue\n}","preventionTips":["Derive model pickers from the live catalog, not hardcoded lists","Add settings migrations when model ids change between releases","Validate persisted ids on load and reset to defaults when unknown"],"tags":["kokoro","model-id","validation","catalog"],"backgroundTag":"invalid-model-id","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-08-23T16:17:53.355Z"}