{"record":{"id":"835d9a7e41285c19","repo":"jamiepine/voicebox","slug":"exception-message-from-wrapped-valueerror","errorCode":null,"errorMessage":"{exception message from wrapped ValueError}","messagePattern":"\\{exception message from wrapped ValueError\\}","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"backend/routes/captures.py","lineNumber":58,"sourceCode":"\n    saved = settings_service.get_capture_settings(db)\n    resolved_stt = stt_model or saved.stt_model\n    if language is None:\n        resolved_language = None if saved.language == \"auto\" else saved.language\n    else:\n        resolved_language = None if language == \"auto\" else language\n\n    try:\n        capture = await captures_service.create_capture(\n            audio_bytes=audio_bytes,\n            filename=file.filename or \"capture.wav\",\n            source=source,\n            language=resolved_language,\n            stt_model=resolved_stt,\n            db=db,\n        )\n    except ValueError as e:\n        raise HTTPException(status_code=400, detail=str(e))\n    except Exception as e:\n        logger.exception(\"Failed to create capture\")\n        raise HTTPException(status_code=500, detail=str(e))\n\n    return models.CaptureCreateResponse(\n        **capture.model_dump(),\n        auto_refine=bool(saved.auto_refine),\n        allow_auto_paste=bool(saved.allow_auto_paste),\n    )\n\n\n@router.get(\"/captures\", response_model=models.CaptureListResponse)\nasync def list_captures_endpoint(\n    limit: int = 50,\n    offset: int = 0,\n    db: Session = Depends(get_db),\n):\n    if limit < 1 or limit > 200:","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/jamiepine/voicebox/blob/51f49dea198384b4eb6087b72c17057c6eb1c1cd/backend/routes/captures.py#L40-L76","documentation":"Returned as a 400 from POST /captures wrapping any ValueError raised by captures_service.create_capture. The service uses ValueError to signal expected, user-correctable problems (unsupported audio format, invalid language code, STT model not available, malformed input) rather than internal failures. The route catches ValueError separately from generic Exception so these surface as 400, not 500. The detail is str(e) — the service's own message.","triggerScenarios":"POST /captures where create_capture raises ValueError: e.g. audio_bytes is a format the STT can't decode, resolved_stt_model is not a known/installed model, resolved language code is invalid, or a sample/source reference is malformed.","commonSituations":"User selected an STT model not yet downloaded; uploaded an audio format the decoder rejects (e.g. mp4 when only wav/16k mono supported); passed an unsupported language string.","solutions":["Read the detail string — it states the exact problem (model missing, format unsupported, bad language).","If model-related, ensure the STT model is downloaded and matches the configured model_size.","If format-related, convert the upload to a supported container/sample rate before posting.","Validate the language field against the allowed set on the client before sending."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pre-validate the inputs the service checks.\nconst allowedLangs = await fetchAllowedLanguages();\nif (language && !allowedLangs.includes(language)) {\n  throw new Error(`Unsupported language: ${language}`);\n}\nif (!await isSttModelInstalled(sttModel)) {\n  throw new Error(`STT model ${sttModel} not available`);\n}","typeGuard":"function isSupportedLanguage(lang: string, allowed: string[]): boolean {\n  return allowed.includes(lang);\n}","tryCatchPattern":"try {\n  const r = await postCapture(fd);\n  if (r.status === 400) {\n    const { detail } = await r.json();\n    showUserFacingError(detail); // service message names the real cause\n    return;\n  }\n} catch (e) { showNetworkError(e); }","preventionTips":["Validate language against the server's allowed set before uploading.","Ensure the selected STT model is downloaded before first capture.","Convert uploads to a supported container/sample rate client-side."],"tags":["capture","stt","validation","input","fastapi"],"backgroundTag":null,"analyzedSha":"51f49dea198384b4eb6087b72c17057c6eb1c1cd","analyzedAt":"2026-08-12T16:51:42.824Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}