unslothai/unsloth · error · HTTPException

Failed to get export logs

Error message

Failed to get export logs

What it means

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.

Source

Thrown at studio/backend/routes/export.py:251

            cursor = max(0, int(since))

        entries, new_cursor = backend.get_logs_since(cursor)
        return {
            "entries": [
                {
                    "seq": int(entry.get("seq", 0)),
                    "stream": entry.get("stream", "stdout"),
                    "line": entry.get("line", ""),
                    "ts": entry.get("ts"),
                }
                for entry in entries
            ],
            "cursor": new_cursor,
            "active": bool(backend.is_export_active()),
        }
    except Exception as e:
        logger.error(f"Error getting export logs: {e}", exc_info = True)
        raise HTTPException(
            status_code = 500,
            detail = "Failed to get export logs",
        )


def _try_register_external_export(
    path: Path, *, refresh_index: bool = False
) -> tuple[bool, Optional[str]]:
    """Best-effort registration so absolute exports show up in local scans."""
    try:
        from storage.studio_db import add_scan_folder_with_status

        folder, inserted = add_scan_folder_with_status(str(path))
        if inserted or refresh_index:
            from core.inference.local_model_resolver import invalidate_index, warm_index_soon
            invalidate_index()
            warm_index_soon()
        return True, str(folder.get("path") or path)

View on GitHub (pinned to 203007d190)

Solutions

  1. Check server logs for 'Error getting export logs' with traceback.
  2. Retry with since omitted to reset the cursor and re-fetch the full buffer.
  3. If the worker crashed, restart the backend to reinitialize the log store.
Defensive patterns

Strategy: retry

Try / catch

try {
  return await api.get('/export/logs', { params: { since: cursor } });
} catch (e) {
  if (e.status === 500) { cursor = null; return api.get('/export/logs'); } // reset cursor and refetch
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: Log tailing during backend shutdown or worker crash; polling with a stale cursor after a backend restart reset the log store.

Related errors


AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15). Data as JSON: /api/errors/26ea1696bea73259. Report an issue: GitHub.