langfuse/langfuse · error · Error

Failed to download trace JSON

Error message

Failed to download trace JSON

What it means

Fallback error from downloadServerTraceAsJson when the GET to the trace export endpoint returns a non-ok response and the body either has no message field or is not JSON. The server's message is preferred when present, so seeing this literal string means the response body was unparseable or message-less.

Source

Thrown at web/src/features/traces/fns/downloadTrace.ts:60

  link.download = filename;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
  URL.revokeObjectURL(url);
}

export async function downloadServerTraceAsJson(
  params: ServerTraceDownloadParams,
) {
  const { traceId, projectId } = params;
  const response = await fetch(buildTraceDownloadUrl({ traceId, projectId }), {
    method: "GET",
    credentials: "same-origin",
  });

  if (!response.ok) {
    const errorBody: unknown = await response.json().catch(() => null);
    throw new Error(
      hasErrorMessage(errorBody)
        ? errorBody.message
        : "Failed to download trace JSON",
    );
  }

  const blob = await response.blob();
  downloadBlob({
    blob,
    filename: `trace-${encodeURIComponent(traceId)}.json`,
  });
}

export function downloadLegacyTraceAsJson(params: LegacyTraceDownloadParams) {
  const { trace, observations, filename } = params;
  const exportData = {
    trace,
    observations,

View on GitHub (pinned to 59d92c7cf3)

Solutions

  1. Inspect response.status in the catch — 404 means the trace id is wrong/deleted, 401/403 means auth, 413 means too large
  2. Re-check the traceId and re-authenticate, then retry the download
  3. For 413, reduce trace size or raise LANGFUSE_API_TRACE_OBSERVATIONS_SIZE_LIMIT_BYTES on self-host

Example fix

// before
if (!response.ok) {
  const errorBody: unknown = await response.json().catch(() => null);
  throw new Error(hasErrorMessage(errorBody) ? errorBody.message : "Failed to download trace JSON");
}

// after (include status for diagnosability)
if (!response.ok) {
  const errorBody: unknown = await response.json().catch(() => null);
  throw new Error(
    hasErrorMessage(errorBody)
      ? `${errorBody.message} (HTTP ${response.status})`
      : `Failed to download trace JSON (HTTP ${response.status})`,
  );
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await downloadServerTraceAsJson(traceId);
} catch (e) {
  const msg = e instanceof Error ? e.message : String(e);
  if (/HTTP 404|not found/i.test(msg)) notifyTraceMissing();
  else if (/HTTP 413|too large/i.test(msg)) notifyTooLarge();
  else notifyDownloadFailed(msg);
}

Prevention

When it happens

Trigger: GET /api/public/traces/{traceId}/export (or the internal download route) returning 404 (trace missing), 401/403 (no access), 413 (trace too large), or an HTML error page from a proxy with a non-JSON body.

Common situations: Trace deleted between viewing and downloading; expired session hitting an auth-redirect HTML page; reverse proxy (nginx/Cloudflare) returning 502 HTML; trace exceeding LANGFUSE_API_TRACE_OBSERVATIONS_SIZE_LIMIT_BYTES.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of langfuse/langfuse@59d92c7cf3 (2026-08-27). Data as JSON: /api/errors/5321d72c9cabfabd. Report an issue: GitHub.