prometheus/prometheus · error · Error

res.statusText

Error message

res.statusText

What it means

Thrown by the mantine-ui API layer when an HTTP response is both non-OK and not application/json (e.g. a plain-text 503 from a starting Prometheus). The wrapper cannot parse a JSON error body, so it surfaces the HTTP status text as the Error message. It is the catch-all for non-JSON transport-level failures.

Source

Thrown at web/ui/mantine-ui/src/api/api.ts:57

      const startTime = Date.now();

      const res = await fetch(
        `${pathPrefix}/${API_PATH}${path}${queryString}`,
        {
          cache: "no-store",
          credentials: "same-origin",
          signal,
        }
      );

      if (
        !res.ok &&
        !res.headers.get("content-type")?.startsWith("application/json")
      ) {
        // For example, Prometheus may send a 503 Service Unavailable response
        // with a "text/plain" content type when it's starting up. But the API
        // may also respond with a JSON error message and the same error code.
        throw new Error(res.statusText);
      }

      const apiRes = (await res.json()) as APIResponse<T>;

      if (recordResponseTime) {
        recordResponseTime(Date.now() - startTime);
      }

      if (apiRes.status === "error") {
        throw new Error(
          apiRes.error !== undefined
            ? apiRes.error
            : 'missing "error" field in response JSON'
        );
      }

      return apiRes as SuccessAPIResponse<T>;
    } catch (error) {

View on GitHub (pinned to 44d6a0e0b1)

Solutions

  1. Wait for Prometheus to finish startup and retry (check /-/ready).
  2. Verify the UI is served by the same Prometheus instance (pathPrefix/external URL config) so fetch hits the real API, not a proxy error page.
  3. If behind a reverse proxy, configure it to pass Prometheus responses through unchanged or return JSON errors.
  4. Handle non-OK responses in the UI with a friendly message using res.status and res.statusText.

Example fix

// before
throw new Error(res.statusText);

// after (include status code for diagnosability)
throw new Error(`${res.status} ${res.statusText}`);
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const data = await fetchAPI<T>('/query', {...});
} catch (err) {
  if (err instanceof Error && /^[1-5]\d\d /.test(err.message)) {
    // non-JSON HTTP error surface: show retry UI, do not crash
  }
}

Prevention

When it happens

Trigger: Any useFetch/useSuspenseAPIQuery request where res.ok is false AND the content-type header does not start with 'application/json' — typically a 503 text/plain from Prometheus during startup, a 404 HTML page from a reverse proxy, or a gateway timeout from a load balancer.

Common situations: Prometheus still starting (WAL replay) behind the UI; wrong --web.external-url/path prefix so the UI hits a proxy error page; ingress/LB returning HTML error pages; server restarting mid-query.

Related errors


AI-assisted analysis of prometheus/prometheus@44d6a0e0b1 (2026-08-15). Data as JSON: /api/errors/e59c9d05107d25ea. Report an issue: GitHub.