{"record":{"id":"a25f89c8a622cf93","repo":"HeyPuter/puter","slug":"field-invalid-a25f89","errorCode":"field_invalid","errorMessage":"Invalid model: ${modelId}. Expected: ${expected.join(', ')}","messagePattern":"Invalid model: (.+?)\\. Expected: (.+?)","errorType":"validation","errorClass":"HttpError","httpStatus":400,"severity":"error","filePath":"src/backend/drivers/ai-tts/providers/elevenlabs/ElevenLabsTTSProvider.ts","lineNumber":225,"sourceCode":"            return { url: SAMPLE_AUDIO_URL, content_type: 'audio' };\n        }\n\n        if (typeof text !== 'string' || !text.trim()) {\n            throw new HttpError(400, 'Missing required field: text', {\n                legacyCode: 'field_required',\n                fields: { key: 'text' },\n            });\n        }\n\n        const voiceId = voiceArg || this.defaultVoiceId;\n        const modelId = modelArg || DEFAULT_MODEL;\n\n        // Gate on the cost table rather than the advertised model list: an id\n        // we can't price is an id we can't bill for, and the vendor bills us\n        // for it either way.\n        if (!Object.hasOwn(ELEVENLABS_TTS_COSTS, modelId)) {\n            const expected = Object.keys(ELEVENLABS_TTS_COSTS);\n            throw new HttpError(\n                400,\n                `Invalid model: ${modelId}. Expected: ${expected.join(', ')}`,\n                {\n                    legacyCode: 'field_invalid',\n                    fields: { key: 'model', expected, got: modelId },\n                },\n            );\n        }\n\n        const desiredFormat =\n            output_format || response_format || DEFAULT_OUTPUT_FORMAT;\n\n        const actor = Context.get('actor')!;\n        const usageKey = `elevenlabs:${modelId}:character`;\n        const ucentsPerChar = ELEVENLABS_TTS_COSTS[modelId];\n        const totalCost = ucentsPerChar * text.length;\n\n        const usageAllowed = await this.meteringService.hasEnoughCredits(","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/HeyPuter/puter/blob/908ec23eda38526170322c3edf71ba45ecb1ca95/src/backend/drivers/ai-tts/providers/elevenlabs/ElevenLabsTTSProvider.ts#L207-L243","documentation":"ElevenLabsTTSProvider gates the model on the cost table, not the advertised model list: if modelId (after defaulting to eleven_multilingual_v2) is not a key in ELEVENLABS_TTS_COSTS, it throws HTTP 400 (legacyCode field_invalid) with fields.key='model', fields.expected, and fields.got. Rationale (per source comment): an id we cannot price is an id we cannot bill for, but the vendor still bills.","triggerScenarios":"Passing model: 'eleven_monolingual_v1' (not in the cost table) or any model id absent from ELEVENLABS_TTS_COSTS, including deprecated or preview ids that ElevenLabs accepts but Puter cannot price.","commonSituations":"Using an old/deprecated model id; passing a brand-new ElevenLabs model before the cost table is updated; typo in the model id; assuming a model is supported because ElevenLabs lists it, when Puter's cost table hasn't added it.","solutions":["Use a model present in the cost table: eleven_multilingual_v2, eleven_flash_v2_5, eleven_turbo_v2_5, eleven_v3 (read fields.expected from the error).","Omit model to accept the default (eleven_multilingual_v2).","Call list_engines({ provider: 'elevenlabs' }) to see supported/priced model ids.","If you need a new model priced, add it to ELEVENLABS_TTS_COSTS in costs.js."],"exampleFix":"// before\nawait driver.synthesize({ text: 'hi', provider: 'elevenlabs', model: 'eleven_monolingual_v1' });\n// after\nawait driver.synthesize({ text: 'hi', provider: 'elevenlabs', model: 'eleven_multilingual_v2' });","handlingStrategy":"validation","validationCode":"// Gate on the priced model set, mirroring ELEVENLABS_TTS_COSTS keys.\nconst PRICED_MODELS = ['eleven_multilingual_v2', 'eleven_flash_v2_5', 'eleven_turbo_v2_5', 'eleven_v3'];\nfunction synthesizeElevenLabs(text, model = 'eleven_multilingual_v2') {\n  if (!PRICED_MODELS.includes(model)) {\n    throw new Error(`Unsupported model: ${model}. Use one of: ${PRICED_MODELS.join(', ')}`);\n  }\n  return driver.synthesize({ text, provider: 'elevenlabs', model });\n}","typeGuard":"const PRICED_MODELS = ['eleven_multilingual_v2', 'eleven_flash_v2_5', 'eleven_turbo_v2_5', 'eleven_v3'] as const;\ntype ElevenLabsModel = typeof PRICED_MODELS[number];\n\nconst isElevenLabsModel = (v: unknown): v is ElevenLabsModel =>\n  typeof v === 'string' && (PRICED_MODELS as readonly string[]).includes(v);","tryCatchPattern":null,"preventionTips":["Let users pick models from list_engines({ provider: 'elevenlabs' }) output, not free text.","When adding a model server-side, update ELEVENLABS_TTS_COSTS at the same time.","Omit model to accept the safe default (eleven_multilingual_v2)."],"tags":["elevenlabs","tts","validation","model","billing"],"backgroundTag":null,"analyzedSha":"908ec23eda38526170322c3edf71ba45ecb1ca95","analyzedAt":"2026-08-12T20:53:15.911Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}