{"record":{"id":"26ea1696bea73259","repo":"unslothai/unsloth","slug":"failed-to-get-export-logs","errorCode":null,"errorMessage":"Failed to get export logs","messagePattern":"Failed to get export logs","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"studio/backend/routes/export.py","lineNumber":251,"sourceCode":"            cursor = max(0, int(since))\n\n        entries, new_cursor = backend.get_logs_since(cursor)\n        return {\n            \"entries\": [\n                {\n                    \"seq\": int(entry.get(\"seq\", 0)),\n                    \"stream\": entry.get(\"stream\", \"stdout\"),\n                    \"line\": entry.get(\"line\", \"\"),\n                    \"ts\": entry.get(\"ts\"),\n                }\n                for entry in entries\n            ],\n            \"cursor\": new_cursor,\n            \"active\": bool(backend.is_export_active()),\n        }\n    except Exception as e:\n        logger.error(f\"Error getting export logs: {e}\", exc_info = True)\n        raise HTTPException(\n            status_code = 500,\n            detail = \"Failed to get export logs\",\n        )\n\n\ndef _try_register_external_export(\n    path: Path, *, refresh_index: bool = False\n) -> tuple[bool, Optional[str]]:\n    \"\"\"Best-effort registration so absolute exports show up in local scans.\"\"\"\n    try:\n        from storage.studio_db import add_scan_folder_with_status\n\n        folder, inserted = add_scan_folder_with_status(str(path))\n        if inserted or refresh_index:\n            from core.inference.local_model_resolver import invalidate_index, warm_index_soon\n            invalidate_index()\n            warm_index_soon()\n        return True, str(folder.get(\"path\") or path)","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/routes/export.py#L233-L269","documentation":"Catch-all HTTP 500 for GET /export/logs: reading buffered log entries, computing the cursor, or calling is_export_active() raised. The traceback is logged; the client gets the generic message. The endpoint supports a `since` cursor for incremental tailing.","triggerScenarios":"GET /export/logs?since=N when the log ring buffer/state is malformed (non-integer seq via int(entry.get('seq', 0)) is guarded, but missing backend init or a corrupted log file is not), or when the backend IPC fails.","commonSituations":"Log tailing during backend shutdown or worker crash; polling with a stale cursor after a backend restart reset the log store.","solutions":["Check server logs for 'Error getting export logs' with traceback.","Retry with since omitted to reset the cursor and re-fetch the full buffer.","If the worker crashed, restart the backend to reinitialize the log store."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  return await api.get('/export/logs', { params: { since: cursor } });\n} catch (e) {\n  if (e.status === 500) { cursor = null; return api.get('/export/logs'); } // reset cursor and refetch\n  throw e;\n}","preventionTips":["Reset the `since` cursor on error rather than polling with a stale one.","Tolerate transient 500s during worker shutdown in log-tail loops."],"tags":["export","logging","http-500","polling"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}