{"record":{"id":"58ca752d606d26ac","repo":"jamiepine/voicebox","slug":"unknown-effect-type-effect-type-at-index-i","errorCode":null,"errorMessage":"Unknown effect type '{effect_type}' at index {i}. Available: {list(EFFECT_REGISTRY.keys())}","messagePattern":"Unknown effect type '(.+?)' at index (.+?)\\. Available: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/services/effects.py","lineNumber":61,"sourceCode":"        return None\n    return _preset_response(p)\n\n\ndef get_preset_by_name(name: str, db: Session) -> Optional[EffectPresetResponse]:\n    \"\"\"Get a preset by name.\"\"\"\n    p = db.query(DBEffectPreset).filter_by(name=name).first()\n    if not p:\n        return None\n    return _preset_response(p)\n\n\ndef create_preset(data: EffectPresetCreate, db: Session) -> EffectPresetResponse:\n    \"\"\"Create a new user effect preset.\"\"\"\n\n    chain_dicts = [e.model_dump() for e in data.effects_chain]\n    error = validate_effects_chain(chain_dicts)\n    if error:\n        raise ValueError(error)\n\n    # Check for duplicate name before insert\n    existing = db.query(DBEffectPreset).filter_by(name=data.name).first()\n    if existing:\n        raise ValueError(f\"A preset named '{data.name}' already exists\")\n\n    preset = DBEffectPreset(\n        id=str(uuid.uuid4()),\n        name=data.name,\n        description=data.description,\n        effects_chain=json.dumps(chain_dicts),\n        is_builtin=False,\n    )\n    db.add(preset)\n    try:\n        db.commit()\n    except IntegrityError:\n        db.rollback()","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/jamiepine/voicebox/blob/51f49dea198384b4eb6087b72c17057c6eb1c1cd/backend/services/effects.py#L43-L79","documentation":"validate_effects_chain() (backend/utils/effects.py) walks each effect dict; if effect['type'] is not a key in EFFECT_REGISTRY it returns this message. create_preset() and update_preset() call validate_effects_chain and raise ValueError with whatever it returns (effects.py:61, effects.py:102). Registered types are: chorus, reverb, delay, compressor, gain, highpass, lowpass, pitch_shift.","triggerScenarios":"POST /presets or PUT /presets/{id} with an effects_chain entry whose 'type' is something like 'echo', 'distortion', or a typo. Also a newer frontend sending an effect name the running backend's EFFECT_REGISTRY doesn't yet know.","commonSituations":"Frontend/backend version skew; hand-edited preset JSON; copy-pasting a raw pedalboard plugin name that isn't wrapped by the registry.","solutions":["Use only registered types: chorus, reverb, delay, compressor, gain, highpass, lowpass, pitch_shift.","Discover supported types and their param schemas at runtime via get_available_effects() (GET /effects).","Update the backend if a new effect type is legitimately required."],"exampleFix":"// before\n{\"type\": \"echo\", \"enabled\": true, \"params\": {\"delay_seconds\": 0.3}}\n\n// after — 'delay' is the registered name\n{\"type\": \"delay\", \"enabled\": true, \"params\": {\"delay_seconds\": 0.3, \"feedback\": 0.3, \"mix\": 0.3}}","handlingStrategy":"validation","validationCode":"from backend.utils.effects import EFFECT_REGISTRY\n\ndef all_types_known(chain):\n    return all(isinstance(e, dict) and e.get(\"type\") in EFFECT_REGISTRY for e in chain)","typeGuard":"from backend.utils.effects import EFFECT_REGISTRY\n\ndef is_known_effect_type(t) -> bool:\n    return isinstance(t, str) and t in EFFECT_REGISTRY","tryCatchPattern":"try:\n    create_preset(data, db)\nexcept ValueError as e:\n    if \"Unknown effect type\" in str(e):\n        # show user available types from get_available_effects()\n        ...\n    raise","preventionTips":["Drive the effects-chain editor from get_available_effects() so only registered types are selectable.","Validate the chain client-side against the same registry before POSTing.","Keep frontend and backend effect-type vocabularies in sync across releases."],"tags":["effects","validation","presets","pedalboard"],"backgroundTag":null,"analyzedSha":"51f49dea198384b4eb6087b72c17057c6eb1c1cd","analyzedAt":"2026-08-12T16:51:42.824Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}