Skip to content
BuildThenTestedSee packages

Errors swallowed, spinner never stops

When a request fails, users see a spinner that never ends or an empty list, assume the app is broken or their data is gone, and nobody on your side hears about it. Whether the app keeps working when something fails. Check it yourself with the steps below; our test adds what a script and a second account can find.

What it looks like

setLoading(true);
try {
  const res = await fetch("/api/orders");
  setOrders(await res.json());
} catch (e) {
  console.log(e); // nothing shown to the user
}
// setLoading(false) only runs on the happy path
A data load where a failed request is logged to the browser console and the loading state is never cleared, so the page shows a spinner with no message.

What happens

When a request fails, users see a spinner that never ends or an empty list, assume the app is broken or their data is gone, and nobody on your side hears about it.

Where it shows up

Descriptive, not a verdict: builders and stacks whose defaults make this reachable, or that a public incident names. Each hub states the tool's own security features.

Check it yourself

Uses your builder's dashboard and your browser. No tools to install.

  1. Open your app in Chrome and sign in as a normal user.
  2. Press F12 to open developer tools, choose the Network tab, and change the throttling dropdown from "No throttling" to "Offline".
  3. Click into a page that loads data, such as your dashboard or a list, and watch for a message on the page.
  4. Set throttling back to "No throttling", then right-click one API request in the Network tab, choose "Block request URL" and reload the page.

Bad result: a spinner that keeps turning, an empty list with no message, or a page that looks normal but shows stale or missing data, while the Console tab fills with red errors.

What we check

We fail each API call the app makes in turn, including responses with error statuses that fetch treats as success, and record which screens show a message, which retry and which hang. The report lists each hanging screen with the request that caused it.

Fix direction

Check response.ok after every fetch and treat a non-OK status as a failure, clear the loading state in a finally block, and show one plain message with a retry button. Send caught errors to an error tracker so failures reach you before users report them.

Mechanism documented in: MDN: Using the Fetch API (verified 2026-09-21).

Covered by

Pre-launch check ($490, 48 hours) and Full audit ($1,900, 5 business days)

Both include a re-check after your fixes.

Compare packages

Related patterns

  • Retries with no pause and no capReliability

    One outage turns into a flood of retries from every open browser tab, which keeps the service down longer, runs up usage bills and can submit the same order or payment twice.

    Medium
  • No rate limiting on sensitive routesReliability

    A script can try thousands of passwords against your login form, hammer a form that sends emails or calls a paid API, or knock the app over, and the bill lands on you.

    High
  • Secrets and internals in error messages and logsSecrets and keys

    Keys, session tokens and database connection strings end up in log files and in HTTP responses that anyone can trigger, which hands out credentials and a map of the system's internals.

    High
  • Background jobs that fail silentlyReliability

    Emails, invoices, syncs or clean-ups quietly stop for some or all users, and you find out weeks later from a customer rather than from the system.

    Medium

Questions

why does my app show a loading spinner forever

Usually a request failed and the code that turns the spinner off only runs when the request succeeds. The error is caught and logged to the console, so the page never learns that it should show a message. Open developer tools, look at the Console and Network tabs while the spinner turns, and you will normally see the failed request in red.

does fetch reject on http error status

No. The browser's fetch function only rejects for network failures such as being offline. A response with an HTTP 404 or HTTP 500 status arrives as a normal response. Code with only a try and catch treats it as success and may try to read an error page as data. Check response.ok before using the body.

how do i know if my ai built app handles errors

Make requests fail on purpose. Set the browser to offline, block a single request URL in developer tools, or turn off your database for a minute in a test project. Every screen should show a plain message and a way to retry; a spinner with no message or a silent blank list means the error is being swallowed.

Back to the catalogue, or run the self-check for your stack.