{"record":{"id":"c3f4408316bf157d","repo":"jamiepine/voicebox","slug":"error-importing-profile-str-e","errorCode":null,"errorMessage":"Error importing profile: {str(e)}","messagePattern":"Error importing profile: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/services/export_import.py","lineNumber":242,"sourceCode":"                        profile.id,\n                        tmp_path,\n                        reference_text,\n                        db,\n                    )\n                finally:\n                    # Clean up temp file\n                    Path(tmp_path).unlink(missing_ok=True)\n            \n            return profile\n            \n    except zipfile.BadZipFile:\n        raise ValueError(\"Invalid ZIP file\")\n    except json.JSONDecodeError as e:\n        raise ValueError(f\"Invalid JSON in archive: {e}\")\n    except Exception as e:\n        if isinstance(e, ValueError):\n            raise\n        raise ValueError(f\"Error importing profile: {str(e)}\")\n\n\ndef export_generation_to_zip(generation_id: str, db: Session) -> bytes:\n    \"\"\"\n    Export a generation to a ZIP archive.\n    \n    Args:\n        generation_id: Generation ID to export\n        db: Database session\n        \n    Returns:\n        ZIP file contents as bytes\n        \n    Raises:\n        ValueError: If generation not found\n    \"\"\"\n    # Get generation\n    generation = db.query(DBGeneration).filter_by(id=generation_id).first()","sourceCodeStart":224,"sourceCodeEnd":260,"githubUrl":"https://github.com/jamiepine/voicebox/blob/51f49dea198384b4eb6087b72c17057c6eb1c1cd/backend/services/export_import.py#L224-L260","documentation":"Catch-all raised by the profile import path for any non-BadZipFile, non-JSONDecodeError, non-ValueError exception that escapes the with-zipfile block (export_import.py:239-242). The original exception's message is appended, so the underlying cause is preserved in the string. This is the wrapper you see when the import failed for a structural reason deeper in create_profile or add_profile_sample.","triggerScenarios":"create_profile raised a DB integrity error (duplicate name not caught by _get_unique_profile_name due to a race); add_profile_sample failed because the disk is full; config.get_profiles_dir() points to an unwritable path; a sample file in samples.json is missing from the archive triggering ValueError already, but any other Exception (OSError, sqlalchemy) lands here.","commonSituations":"Storage volume full or read-only; DB unique constraint violation from a concurrent import; permissions wrong on the profiles directory; the underlying ValueError messages (e.g. 'Invalid sample filename') are re-raised verbatim by the isinstance(e, ValueError) check, so what you see here is genuinely a non-ValueError.","solutions":["Read the {str(e)} tail to identify the underlying exception type — that drives the fix.","If it is an OSError/PermissionError, check write permissions and free space on the volume backing config.get_profiles_dir().","If it is a sqlalchemy IntegrityError, inspect for duplicate profile names or concurrent imports hitting _get_unique_profile_name.","If it is a KeyError/AttributeError from manifest data, the export format is mismatched — re-export from a matching version."],"exampleFix":"# before: profiles dir not writable\n# config.get_profiles_dir() -> /readonly/profiles\n# after: point config at a writable dir and retry\nexport PROFILES_DIR=/var/lib/voicebox/profiles","handlingStrategy":"try-catch","validationCode":"null","typeGuard":"null","tryCatchPattern":"try:\n    profile = await import_profile_from_bytes(file_bytes, db)\nexcept ValueError as e:\n    msg = str(e)\n    if msg.startswith('Error importing profile:'):\n        # underlying cause is in the tail — log it for ops\n        logger.exception('profile import failed: %s', msg)\n        raise HTTPException(500, 'Profile import failed; see server logs.')\n    raise HTTPException(400, msg)","preventionTips":["Ensure config.get_profiles_dir() exists and is writable before enabling imports.","Run imports inside a DB transaction so partial profile rows roll back on failure.","Monitor free disk space on the storage volume.","Log the full underlying exception, not just the wrapped message."],"tags":["import","catch-all","filesystem","database"],"backgroundTag":null,"analyzedSha":"51f49dea198384b4eb6087b72c17057c6eb1c1cd","analyzedAt":"2026-08-12T16:51:42.824Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}