{"record":{"id":"d25ff86ecf6cb8b1","repo":"jamiepine/voicebox","slug":"cloned-profiles-cannot-use-default-engine-defaul","errorCode":null,"errorMessage":"Cloned profiles cannot use default engine '{default_engine}'","messagePattern":"Cloned profiles cannot use default engine '(.+?)'","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/services/profiles.py","lineNumber":173,"sourceCode":"    existing_profile = db.query(DBVoiceProfile).filter_by(name=data.name).first()\n    if existing_profile:\n        raise ValueError(f\"A profile with the name '{data.name}' already exists. Please choose a different name.\")\n\n    # Auto-set default_engine for preset profiles\n    default_engine = data.default_engine\n    voice_type = data.voice_type or \"cloned\"\n    if voice_type == \"preset\" and data.preset_engine and not default_engine:\n        default_engine = data.preset_engine\n\n    validation_error = _validate_profile_fields(\n        voice_type=voice_type,\n        preset_engine=data.preset_engine,\n        preset_voice_id=data.preset_voice_id,\n        design_prompt=data.design_prompt,\n        default_engine=default_engine,\n    )\n    if validation_error:\n        raise ValueError(validation_error)\n\n    db_profile = DBVoiceProfile(\n        id=str(uuid.uuid4()),\n        name=data.name,\n        description=data.description,\n        language=data.language,\n        voice_type=voice_type,\n        preset_engine=data.preset_engine,\n        preset_voice_id=data.preset_voice_id,\n        design_prompt=data.design_prompt,\n        default_engine=default_engine,\n        personality=data.personality,\n        created_at=datetime.utcnow(),\n        updated_at=datetime.utcnow(),\n    )\n\n    db.add(db_profile)\n    db.commit()","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/jamiepine/voicebox/blob/51f49dea198384b4eb6087b72c17057c6eb1c1cd/backend/services/profiles.py#L155-L191","documentation":"Returned by _validate_profile_fields for the cloned branch when default_engine is set and is not in CLONING_ENGINES = {qwen, luxtts, chatterbox, chatterbox_turbo, tada}. Cloned profiles can only be synthesized by engines that support voice cloning; preset-only engines like kokoro/qwen_custom_voice are rejected here.","triggerScenarios":"POSTing voice_type:'cloned' (or omitted) with default_engine:'kokoro' or any value outside the cloning set.","commonSituations":"Defaulting default_engine to a global TTS setting that happens to be a preset-only engine; upgrading the backend and an engine name changed; typo in the engine string.","solutions":["Set default_engine to a cloning-capable engine: one of qwen, luxtts, chatterbox, chatterbox_turbo, tada.","Omit default_engine to let the backend pick the default cloning engine.","If you actually want kokoro/qwen_custom_voice, that is a preset voice — use voice_type:'preset' instead."],"exampleFix":"// before\n{\"name\":\"Echo\",\"voice_type\":\"cloned\",\"default_engine\":\"kokoro\"}\n// after\n{\"name\":\"Echo\",\"voice_type\":\"cloned\",\"default_engine\":\"chatterbox\"}","handlingStrategy":"validation","validationCode":"CLONING_ENGINES = {\"qwen\", \"luxtts\", \"chatterbox\", \"chatterbox_turbo\", \"tada\"}\n\ndef cloned_engine_ok(data) -> bool:\n    vt = data.voice_type or \"cloned\"\n    return vt != \"cloned\" or not data.default_engine or data.default_engine in CLONING_ENGINES\n\nif not cloned_engine_ok(data):\n    raise HTTPException(400, f\"{data.default_engine} is not a cloning engine\")","typeGuard":"def is_valid_cloned_engine(engine: str | None) -> bool:\n    return engine is None or engine in {\"qwen\", \"luxtts\", \"chatterbox\", \"chatterbox_turbo\", \"tada\"}","tryCatchPattern":null,"preventionTips":["Restrict the cloned-profile engine dropdown to CLONING_ENGINES in the UI.","Omit default_engine to use the backend default rather than guessing.","Remember kokoro/qwen_custom_voice are preset-only and cannot clone."],"tags":["profiles","cloned","validation","create","invalid-engine"],"backgroundTag":null,"analyzedSha":"51f49dea198384b4eb6087b72c17057c6eb1c1cd","analyzedAt":"2026-08-12T16:51:42.824Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}