{"record":{"id":"a1949790584be15f","repo":"jamiepine/voicebox","slug":"version-not-found-a19497","errorCode":null,"errorMessage":"Version not found","messagePattern":"Version not found","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"error","filePath":"backend/routes/effects.py","lineNumber":236,"sourceCode":"\n    return version\n\n\n@router.put(\n    \"/generations/{generation_id}/versions/{version_id}/set-default\",\n    response_model=models.GenerationVersionResponse,\n)\nasync def set_default_version(\n    generation_id: str,\n    version_id: str,\n    db: Session = Depends(get_db),\n):\n    \"\"\"Set a specific version as the default for a generation.\"\"\"\n    from ..services import versions as versions_mod\n\n    version = versions_mod.get_version(version_id, db)\n    if not version or version.generation_id != generation_id:\n        raise HTTPException(status_code=404, detail=\"Version not found\")\n\n    result = versions_mod.set_default_version(version_id, db)\n    if not result:\n        raise HTTPException(status_code=404, detail=\"Version not found\")\n    return result\n\n\n@router.delete(\"/generations/{generation_id}/versions/{version_id}\")\nasync def delete_generation_version(\n    generation_id: str,\n    version_id: str,\n    db: Session = Depends(get_db),\n):\n    \"\"\"Delete a version. Cannot delete the last remaining version.\"\"\"\n    from ..services import versions as versions_mod\n\n    version = versions_mod.get_version(version_id, db)\n    if not version or version.generation_id != generation_id:","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/jamiepine/voicebox/blob/51f49dea198384b4eb6087b72c17057c6eb1c1cd/backend/routes/effects.py#L218-L254","documentation":"Returned as HTTP 404 by the set-default-version endpoint for /generations/{generation_id}/versions/{version_id}. The route fetches the version via versions.get_version(version_id) and additionally requires version.generation_id == generation_id. If the version does not exist, or it exists but belongs to a different generation, this 404 is raised. The mismatch check prevents cross-generation default promotion.","triggerScenarios":"Passing a version_id that does not exist; passing a version id from a different generation; the version was deleted between page load and the set-default call; swapping generation_id and version_id in the URL.","commonSituations":"Stale version list in the UI after a delete; user has multiple generations open and the wrong one's version is set as default; client reuses a cached version id after regeneration created new versions; URL path argument ordering mistake.","solutions":["Source version_id and generation_id from a fresh GET /generations/{generation_id}/versions response.","On 404, re-fetch the versions list and re-render the picker.","Ensure the version's generation_id matches the path generation_id client-side before the call.","Double-check URL template ordering: /generations/{generation_id}/versions/{version_id}."],"exampleFix":"// before\napi.post(`/generations/${genId}/versions/${cachedVersionId}/default`)\n// after\nconst versions = await api.get(`/generations/${genId}/versions`);\nconst v = versions.find(x => x.id === cachedVersionId);\nif (!v || v.generation_id !== genId) return;\napi.post(`/generations/${genId}/versions/${v.id}/default`)","handlingStrategy":"validation","validationCode":"v = versions_mod.get_version(version_id, db)\nif v is None or v.generation_id != generation_id:\n    raise VersionNotInGeneration(version_id, generation_id)\n# safe to call set-default-version","typeGuard":"def version_belongs_to_generation(version, generation_id: str) -> bool:\n    return version is not None and version.generation_id == generation_id","tryCatchPattern":"try:\n    client.post(f'/generations/{gen_id}/versions/{ver_id}/default')\nexcept HTTPStatusError as e:\n    if e.response.status_code == 404:\n        versions = client.get(f'/generations/{gen_id}/versions').json()\n        repopulate_picker(versions)\n        return\n    raise","preventionTips":["Source both ids from a fresh versions listing.","Confirm v.generation_id === genId client-side before the call.","On 404, re-fetch versions and rebuild the picker.","Keep URL template argument order straight: /generations/{genId}/versions/{verId}."],"tags":["fastapi","http-404","generations","versions","not-found","ownership","rest"],"backgroundTag":null,"analyzedSha":"51f49dea198384b4eb6087b72c17057c6eb1c1cd","analyzedAt":"2026-08-12T16:51:42.824Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}