ankane/pghero · error · Error

response.statusText

Error message

response.statusText

What it means

PgHero's queries page refreshes stats with fetch() to the /pghero/queries path (XHR header X-Requested-With: XMLHttpRequest). When the server answers with a non-2xx status, response.ok is false and the code throws new Error(response.statusText); the .catch handler paints that message in red inside the .queries-info element. So the visible text is the HTTP status phrase (e.g. "Internal Server Error", "Unauthorized") of the failed backend request, not a JavaScript bug.

Source

Thrown at app/assets/javascripts/pghero/application.js:138

    const showAll = document.getElementById("show-all");
    if (showAll) {
      const showAllParams = Object.assign({}, params);
      delete showAllParams.user;
      showAll.setAttribute("href", queriesPath(showAllParams));
    }

    for (const link of document.querySelectorAll(".queries-table th a")) {
      const linkParams = Object.assign({}, params, {sort: link.getAttribute("data-sort")});
      link.setAttribute("href", queriesPath(linkParams));
    }

    const queries = document.getElementById("queries");
    queries.innerHTML = '<tr><td colspan="3"><p class="queries-info text-muted">...</p></td></tr>';
    const path = queriesPath(params);
    fetch(path, {headers: {"X-Requested-With": "XMLHttpRequest"}})
      .then(function (response) {
        if (!response.ok) {
          throw new Error(response.statusText);
        }
        return response.text();
      })
      .then(function (text) {
        queries.innerHTML = text;
        highlightQueries();
      })
      .catch(function (error) {
        const queriesInfo = document.querySelector(".queries-info");
        queriesInfo.style.color = "red";
        queriesInfo.textContent = error.message;
      });

    if (push && history.pushState) {
      history.pushState(null, null, path);
    }
  }

View on GitHub (pinned to 7edb57986f)

Solutions

  1. Open the browser Network tab, find the failing queries request, and read the response body - it contains the real Rails error (e.g. "Query stats not enabled")
  2. Fix the server-side cause: for query stats, run PgHero.databases["primary"].enable_query_stats (requires pg_stat_statements in shared_preload_libraries); for connection errors, fix the url in config/pghero.yml
  3. If the status is 401/403, verify PGHERO_USERNAME/PGHERO_PASSWORD or the username/password keys in pghero.yml and that the browser is authenticated
  4. If the status is 502/504, check that the Rails app process and any reverse proxy in front of it are up

Example fix

// before
if (!response.ok) {
  throw new Error(response.statusText);
}

// after - surface status plus the server error body
if (!response.ok) {
  const body = await response.text();
  throw new Error(response.status + " " + response.statusText + ": " + body);
}
Defensive patterns

Strategy: try-catch

Try / catch

fetch(path, {headers: {"X-Requested-With": "XMLHttpRequest"}})
  .then(function (response) {
    if (!response.ok) {
      return response.text().then(function (body) {
        throw new Error(response.status + " " + response.statusText + ": " + body);
      });
    }
    return response.text();
  })
  .catch(function (error) {
    // keep a .queries-info element in the DOM so the message has somewhere to render
    console.error("PgHero queries fetch failed", error);
    showErrorMessage(error.message);
  });

Prevention

When it happens

Trigger: Changing any filter on the queries page (time range via the noUiSlider, sort links, user, min_average_time/min_calls) calls refreshStats -> fetch(queriesPath(params)). A 500 is returned when Rails raises on that request, most commonly PgHero::NotEnabled "Query stats not enabled" (pg_stat_statements missing) or a PgHero::Error from a bad database url in config/pghero.yml. A 401/403 is returned when PgHero HTTP auth (username/password) rejects the request; 502/504 when a proxy in front cannot reach the Rails app.

Common situations: Fresh pghero install where pg_stat_statements is not installed and the user opens the Queries tab; misconfigured config/pghero.yml (empty or wrong url); session expired behind PgHero.username/password basic auth; reverse proxy or tunnel down while the dashboard stays open.


AI-assisted analysis of ankane/pghero@7edb57986f (2026-08-21). Data as JSON: /api/errors/ff639d75a451c7fa. Report an issue: GitHub.