{"record":{"id":"94adb75996dc855f","repo":"unslothai/unsloth","slug":"failed-to-cleanup-export-memory","errorCode":null,"errorMessage":"Failed to cleanup export memory","messagePattern":"Failed to cleanup export memory","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"studio/backend/routes/export.py","lineNumber":144,"sourceCode":"    try:\n        backend = get_export_backend()\n        success = await asyncio.to_thread(backend.cleanup_memory)\n\n        if not success:\n            raise HTTPException(\n                status_code = 500,\n                detail = \"Memory cleanup failed. See server logs for details.\",\n            )\n\n        return ExportOperationResponse(\n            success = True,\n            message = \"Memory cleanup completed successfully\",\n        )\n    except HTTPException:\n        raise\n    except Exception as e:\n        logger.error(f\"Error during export memory cleanup: {e}\", exc_info = True)\n        raise HTTPException(\n            status_code = 500,\n            detail = \"Failed to cleanup export memory\",\n        )\n\n\n@router.post(\"/cancel\", response_model = ExportOperationResponse)\nasync def cancel_export(current_subject: str = Depends(get_current_subject)):\n    \"\"\"Cancel the in-flight export by terminating its worker subprocess.\n\n    Only the export subprocess is killed; training and inference run in their\n    own subprocesses and keep going.\n    \"\"\"\n    try:\n        backend = get_export_backend()\n        cancelled = await asyncio.to_thread(backend.cancel_export)\n        return ExportOperationResponse(\n            success = True,\n            message = \"Export cancelled\" if cancelled else \"No active export to cancel\",","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/routes/export.py#L126-L162","documentation":"Catch-all HTTP 500 for the cleanup endpoint: cleanup_memory raised an unexpected exception (rather than returning False). The traceback is logged as 'Error during export memory cleanup'; the client only sees the generic message.","triggerScenarios":"POST /export/cleanup when get_export_backend() or backend.cleanup_memory throws — e.g. backend not initialized, IPC to the worker failing because the worker already died, or an environment with no accelerator library present.","commonSituations":"Calling cleanup after the worker crashed; calling it on a fresh backend before any checkpoint was loaded; driver/library mismatch raising inside the memory-free helper.","solutions":["Read the server log traceback for 'Error during export memory cleanup'.","If the worker subprocess died, restart the backend rather than retrying cleanup against a dead IPC channel.","Treat cleanup as best-effort in clients: a 500 here usually does not block subsequent loads."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await api.post('/export/cleanup');\n} catch (e) {\n  if (e.status === 500) { /* best-effort; check backend logs */ }\n}","preventionTips":["Do not call cleanup against a crashed worker — restart the backend instead.","Make cleanup idempotent and non-blocking in client flows."],"tags":["export","memory","http-500","cleanup"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}