Seeing “Http failure response for … : 0 Unknown Error” in your Angular or Ionic app? Status 0 hides the real reason, so this guide shows how to find it in DevTools and fix the 7 most common causes: CORS, a server that is down, HTTPS and certificate problems, a wrong URL, phone and emulator networking, and blockers.
Your Angular or Ionic app calls your API, and the console shows this instead of a useful message:
ERROR HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: 'Unknown Error',url: 'http://localhost:3000/api/users', ok: false, …}
Http failure response for http://localhost:3000/api/users: 0 Unknown Error
The most confusing part is that there is no server message, no JSON and no real error code. That is normal for this error, and the next section explains why.
What Does Status 0 Mean?
HTTP status codes such as 200, 404 or 500 come from a server. Status 0 is not a real HTTP status. It is what the browser reports when the request never produced a response your code is allowed to read. The request may have been blocked by the browser, or it may never have reached the server at all.
Angular cannot tell you more, because the browser hides the details for security reasons. The real reason is shown only in the browser’s own DevTools. That is where you should look first.
Step 1: Find the Real Reason in DevTools
Open DevTools in your browser and check two tabs:
- Console: look for red messages that mention CORS, Mixed Content or a certificate.
- Network: click the failed request. The status column shows
(failed), and the message next to it, such asnet::ERR_CONNECTION_REFUSED, names the cause.
| What you see | Likely cause | Go to |
|---|---|---|
blocked by CORS policy | The server does not allow your origin or header | Step 3 |
net::ERR_CONNECTION_REFUSED | Server is not running, or the wrong port or address | Steps 2 and 6 |
Mixed Content message | An HTTPS page calls an HTTP API | Step 4 |
net::ERR_CERT_AUTHORITY_INVALID or other ERR_CERT_... | Self-signed, expired or mismatched certificate | Step 5 |
net::ERR_NAME_NOT_RESOLVED | Wrong host name, or DNS problem | Step 6 |
net::ERR_CLEARTEXT_NOT_PERMITTED | Plain HTTP blocked in the Android app | Step 7 |
net::ERR_BLOCKED_BY_CLIENT | An ad blocker or browser extension blocked it | Step 8 |
Step 2: Check That the Server Is Reachable
Test the API without the browser. If this also fails, the problem is the server or the network, not Angular:
curl -i http://localhost:3000/api/users
If curl cannot connect, check these:
- The server process is running and did not crash. Look at its terminal output.
- The port in your Angular code matches the port the server listens on.
- The server did not start on a different port because the usual one was busy.
- A firewall is not blocking the port, especially when you call the API from another device.
Step 3: Fix CORS
When the console says blocked by CORS policy, the server did not send the permission headers the browser needs, and Angular reports it as status 0. The fix is on the server: allow your app’s exact origin and any custom headers such as Authorization. One detail that surprises many people is that error responses need the CORS headers too. If your API crashes with a 500 before the CORS middleware runs, the browser shows a CORS error and status 0 instead of the real 500. I explain the full setup, including Ionic and Capacitor origins, in my guide on fixing CORS errors in Node.js, Angular and Ionic.
Step 4: Fix Mixed Content (HTTPS Page, HTTP API)
If your app is served over HTTPS but calls an http:// API, the browser blocks the request. The console message starts with Mixed Content. This often appears after you deploy: everything worked on http://localhost, but the live site uses HTTPS. The fix is to serve your API over HTTPS as well, and to keep the base URL in one place:
// environment.prod.tsexport const environment = { production: true, apiUrl: 'https://api.example.com'};
// in a servicethis.http.get(`${environment.apiUrl}/api/users`);
My guide on securing your Node.js API with HTTPS and SSL covers the server side.
Step 5: Fix Certificate Problems
An HTTPS request fails with status 0 when the browser does not trust the server’s certificate. Typical causes are a self-signed certificate, an expired certificate, or a certificate issued for a different domain name than the one in your URL. The Network tab shows a message starting with net::ERR_CERT_.
- Production: use a certificate from a trusted authority, such as a free Let’s Encrypt certificate, and make sure it covers the exact host name you call and has not expired.
- Local development with HTTPS: create a certificate that your computer trusts, using a tool such as
mkcert, instead of clicking through browser warnings.
Mobile apps are stricter than desktop browsers about certificates, so a self-signed certificate that you accepted once in Chrome will still fail inside your app.
Step 6: Check the API URL and Host Name
A small typo or a stale URL causes many status 0 errors. Check the exact URL in the failed request, and compare it letter by letter:
- Wrong host name, which shows
ERR_NAME_NOT_RESOLVED. - Wrong port number, or
httpwhere you meanthttps. - A missing
/apiprefix, or one added twice. - The development URL left in the production build, so the deployed app calls
localhost. Use the environment files, as in Step 4, and check which one your build uses.
Step 7: Fix Phones and Emulators (Ionic and Capacitor)
This is the most common cause in Ionic apps that work in the browser but fail on a device:
- localhost means the device itself. On the Android emulator, your computer is reachable at
10.0.2.2. On a real phone, use your computer’s local network IP address, and keep both on the same Wi-Fi. - The server must accept outside connections. A server that listens only on
127.0.0.1cannot be reached from a phone. Start it on all interfaces, for exampleapp.listen(3000, '0.0.0.0'), and allow the port through your firewall. - Plain HTTP is blocked on Android. The error is
ERR_CLEARTEXT_NOT_PERMITTED. Use HTTPS, or for local development only, setserver: { cleartext: true }incapacitor.config.tsand runnpx cap sync android. - iOS also restricts plain HTTP through App Transport Security. Use HTTPS, or add a development-only exception in your iOS project settings, and remove it before release.
Step 8: Rule Out Ad Blockers, Extensions and VPNs
If the Network tab shows net::ERR_BLOCKED_BY_CLIENT, something in your browser blocked the request. Ad blockers sometimes block URLs that contain words such as ads, track or analytics, even in your own API. Open the app in a private window with extensions disabled, or rename the endpoint. A company VPN, proxy or antivirus program can also interfere, so test on another network if everything else looks right.
Step 9: Show a Clear Message Instead of “Unknown Error”
Once the cause is fixed, make your app handle status 0 on purpose, so users do not see a blank screen when the network drops:
import { HttpErrorResponse } from '@angular/common/http';import { catchError, throwError } from 'rxjs';
this.http.get('/api/users').pipe( catchError((err: HttpErrorResponse) => { if (err.status === 0) { console.error('Network or CORS error', err); this.message = 'Cannot reach the server. Check your connection and try again.'; } else { this.message = `Server error ${err.status}`; } return throwError(() => err); })).subscribe((users) => (this.users = users));
You can put the same logic into an HTTP interceptor so every request gets consistent error handling.
Debug Checklist
- Open DevTools and read the Console and the Network status for the failed request.
- Run the same URL with
curl. If it fails, fix the server or network first. - Check the exact URL, port and protocol in the failed request.
- If the console mentions CORS, check the server headers, including on error responses.
- On a phone or emulator, replace
localhostwith10.0.2.2or your computer’s IP, and check the cleartext settings. - Test in a private window with extensions off.
Conclusion
Status 0 is not an error from your server. It means the browser stopped the request, or the request never arrived. Open DevTools and read the real reason, then fix that layer: the server, CORS, HTTPS, the certificate, the URL, the device network or a blocker. Add a clear error message in your app, and the next outage will be easy to understand.

0 Comments