Zie619/n8n-workflows · error · Error

HTTP ${response.status}: ${response.statusText}

Error message

HTTP ${response.status}: ${response.statusText}

What it means

Client-side error thrown by the SPA's shared apiCall() helper in static/index.html whenever fetch() to /api/* returns a non-2xx status. The message only carries the numeric status and status text, so the FastAPI 'detail' payload from the server (e.g. 'Rate limit exceeded', 'Invalid filename format') is discarded. It marks every server-side error condition (400/401/403/404/429/500/503) as a generic Error in the browser.

Source

Thrown at static/index.html:1256

      debounceSearch() {
        clearTimeout(this.searchDebounceTimer);
        this.searchDebounceTimer = setTimeout(() => {
          this.state.currentPage = 1;
          this.resetAndSearch();
        }, 300);
      }

      async apiCall(endpoint, options = {}) {
        const response = await fetch(`/api${endpoint}`, {
          headers: {
            'Content-Type': 'application/json',
            ...options.headers
          },
          ...options
        });

        if (!response.ok) {
          throw new Error(`HTTP ${response.status}: ${response.statusText}`);
        }

        return response.json();
      }

      async loadInitialData() {
        this.showState('loading');

        try {
          // Load categories first, then stats and workflows
          console.log('Loading categories...');
          await this.loadCategories();

          console.log('Categories loaded, populating filter...');
          this.populateCategoryFilter();

          // Load stats and workflows in parallel
          console.log('Loading stats and workflows...');

View on GitHub (pinned to 94007c1445)

Solutions

  1. Identify the failing request in the browser Network tab and match the status code to the server handler raising it (400 filename, 404 not found, 429 rate limit, 500 database/file).
  2. For 429, wait for the rate-limit window to reset and reduce request frequency (the UI fires several apiCall()s on load).
  3. For 404s, re-run the indexer so database metadata matches files on disk, and confirm the file sits inside a subdirectory of workflows/.
  4. Improve apiCall() to read and surface response.json().detail so server error messages are visible.
  5. For 500s, check the api_server.py console output; every server handler logs the underlying exception before responding.

Example fix

// before
if (!response.ok) {
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}

// after
if (!response.ok) {
  let detail = `${response.status} ${response.statusText}`;
  try {
    const body = await response.json();
    if (body && body.detail) detail = `${response.status}: ${body.detail}`;
  } catch (_) {}
  throw new Error(detail);
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const data = await this.apiCall(endpoint);
} catch (err) {
  if (/429/.test(err.message)) { /* back off and retry once */ }
  else if (/404/.test(err.message)) { /* refresh listing, drop stale item */ }
  else { this.showError(err.message); }
}

Prevention

When it happens

Trigger: Any call through this.apiCall(endpoint) that hits a failing endpoint: requesting /api/workflows/<filename> with a malformed filename (400), more than the allowed requests per window from the same IP (429), a workflow present in the UI list but missing from disk (404), or any 500 from the Python handlers when the SQLite DB is missing or unreadable.

Common situations: Clicking a workflow card after the backing JSON file was moved out of workflows/ subdirectories; bursting refreshes and tripping the per-IP rate limiter; running the UI against a server started before workflows were indexed; browsers where HTTP/2 status text is empty, yielding opaque 'HTTP 429: ' messages.

Related errors


AI-assisted analysis of Zie619/n8n-workflows@94007c1445 (2026-08-15). Data as JSON: /api/errors/66c88f31fb6bb144. Report an issue: GitHub.