{"record":{"id":"9f348522b3e8b716","repo":"jamiepine/voicebox","slug":"preset-profiles-must-use-their-preset-engine-as-de","errorCode":null,"errorMessage":"Preset profiles must use their preset_engine as default_engine","messagePattern":"Preset profiles must use their preset_engine as 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 when voice_type=='preset', a default_engine was supplied, and default_engine != preset_engine. A preset profile's synthesis engine is fixed by its preset, so default_engine must either equal preset_engine or be omitted (create_profile auto-fills it from preset_engine).","triggerScenarios":"POSTing a preset profile with default_engine set to a different engine than preset_engine, e.g. preset_engine:'kokoro' and default_engine:'qwen'.","commonSituations":"Copy-pasting a cloned-profile template that carries default_engine:'qwen' and switching voice_type to 'preset' without clearing default_engine; UI pre-populating default_engine from a global setting.","solutions":["Drop default_engine from the request and let create_profile auto-fill it from preset_engine.","Or set default_engine equal to preset_engine explicitly.","Audit the client form: default_engine should be read-only/hidden when voice_type is 'preset'."],"exampleFix":"// before\n{\"voice_type\":\"preset\",\"preset_engine\":\"kokoro\",\"preset_voice_id\":\"af_heart\",\"default_engine\":\"qwen\"}\n// after - omit default_engine\n{\"voice_type\":\"preset\",\"preset_engine\":\"kokoro\",\"preset_voice_id\":\"af_heart\"}","handlingStrategy":"validation","validationCode":"def normalize_preset_default_engine(data):\n    # for preset profiles, default_engine must equal preset_engine or be None\n    if data.voice_type == \"preset\" and data.default_engine and data.default_engine != data.preset_engine:\n        data.default_engine = None  # let the service auto-fill from preset_engine\n    return data","typeGuard":"def preset_engine_consistent(data) -> bool:\n    if data.voice_type != \"preset\":\n        return True\n    de = getattr(data, \"default_engine\", None)\n    return de is None or de == data.preset_engine","tryCatchPattern":null,"preventionTips":["Treat default_engine as read-only for preset profiles in the UI.","Let the backend auto-fill default_engine from preset_engine by simply not sending it.","When cloning a preset profile template, clear default_engine first."],"tags":["profiles","preset","validation","create","engine-mismatch"],"backgroundTag":null,"analyzedSha":"51f49dea198384b4eb6087b72c17057c6eb1c1cd","analyzedAt":"2026-08-12T16:51:42.824Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}