{"record":{"id":"04b4df1ddb5a15b7","repo":"jamiepine/voicebox","slug":"sample-not-found-04b4df","errorCode":null,"errorMessage":"Sample not found","messagePattern":"Sample not found","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"warning","filePath":"backend/routes/profiles.py","lineNumber":211,"sourceCode":"\n@router.get(\"/profiles/{profile_id}/samples\", response_model=list[models.ProfileSampleResponse])\nasync def get_profile_samples(\n    profile_id: str,\n    db: Session = Depends(get_db),\n):\n    \"\"\"Get all samples for a profile.\"\"\"\n    return await profiles.get_profile_samples(profile_id, db)\n\n\n@router.delete(\"/profiles/samples/{sample_id}\")\nasync def delete_profile_sample(\n    sample_id: str,\n    db: Session = Depends(get_db),\n):\n    \"\"\"Delete a profile sample.\"\"\"\n    success = await profiles.delete_profile_sample(sample_id, db)\n    if not success:\n        raise HTTPException(status_code=404, detail=\"Sample not found\")\n    return {\"message\": \"Sample deleted successfully\"}\n\n\n@router.put(\"/profiles/samples/{sample_id}\", response_model=models.ProfileSampleResponse)\nasync def update_profile_sample(\n    sample_id: str,\n    data: models.ProfileSampleUpdate,\n    db: Session = Depends(get_db),\n):\n    \"\"\"Update a profile sample's reference text.\"\"\"\n    sample = await profiles.update_profile_sample(sample_id, data.reference_text, db)\n    if not sample:\n        raise HTTPException(status_code=404, detail=\"Sample not found\")\n    return sample\n\n\n@router.post(\"/profiles/{profile_id}/avatar\", response_model=models.VoiceProfileResponse)\nasync def upload_profile_avatar(","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/jamiepine/voicebox/blob/51f49dea198384b4eb6087b72c17057c6eb1c1cd/backend/routes/profiles.py#L193-L229","documentation":"DELETE /profiles/samples/{sample_id} calls profiles.delete_profile_sample; if it returns falsy the route raises 404 'Sample not found'. The id did not match a sample row, or the row was already deleted. Note this route is keyed on sample_id alone (no profile_id in the path), so the 4040 cannot tell you whether the parent profile exists.","triggerScenarios":"DELETE on a sample_id already removed; a typo in the id; a stale UI list referencing a sample deleted by another session; deleting a sample whose row was cleaned up by a storage-reconciliation job.","commonSituations":"Double-click delete; client cache out of sync; re-running a deletion script after it already succeeded.","solutions":["Treat the 404 as success for idempotent delete workflows.","Refresh the sample list via GET /profiles/{profile_id}/samples to confirm whether the id still exists.","Disable the delete control client-side after the first click to prevent double-submit."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"resp = await client.delete(f\"/profiles/samples/{sample_id}\")\nif resp.status_code == 404:\n    # Already gone -- acceptable for idempotent delete\n    pass\nelse:\n    resp.raise_for_status()\nremove_from_ui(sample_id)","preventionTips":["Treat sample-delete 404 as success.","Refresh the sample list after deletion to keep client state consistent.","Disable the delete button after first click."],"tags":["fastapi","sample","delete","not-found","idempotency"],"backgroundTag":null,"analyzedSha":"51f49dea198384b4eb6087b72c17057c6eb1c1cd","analyzedAt":"2026-08-12T16:51:42.824Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}