174

I'm using Angular 4 HttpClient to send requests to external service. It is a very standard setup:

this.httpClient.get(url).subscribe(response => {
  //do something with response
}, err => {
  console.log(err.message);
}, () => {
  console.log('completed');
}

The problem is, when the request fails I see a generic Http failure response for (unknown url): 0 Unknown Error message in console. Meanwhile, when I inspect the failed request in chrome I can see the response status is 422, and in the "preview" tab I see the actual message desribing failure cause.

How do I access the actual response message I can see in chrome dev tools?

Here's a screenshot demonstrating the problem: enter image description here

Patrick
  • 17,669
  • 6
  • 70
  • 85
grdl
  • 3,640
  • 3
  • 21
  • 25
  • 1
    try to log entire `err` object - not only the `message` – Pavel Agarkov Nov 08 '17 at 14:17
  • I'm facing the same problem and was going to create a question for this too, here's the complete err object: https://gist.github.com/GO3LIN/7cffc3b0aa1f24d3e23e28cc907237fc – Mehdi Benmoha Nov 08 '17 at 14:43
  • 1
    Or better {"headers":{"normalizedNames":{},"lazyUpdate":null,"headers":{}},"status":0,"statusText":"Unknown Error","url":null,"ok":false,"name":"HttpErrorResponse","message":"Http failure response for (unknown url): 0 Unknown Error","error":{"isTrusted":true}} – Mehdi Benmoha Nov 08 '17 at 14:46
  • @PavelAgarkov, It's not about logging only message. The HttpErrorResponse I recveive just doesn't contain the actual error message. Here's a [screenshot](https://imgur.com/B8b47cE) of the problem. You can see there that the error I log has message saying "... unknown error..." but when you look at the request response preview above you can see the actual, meaningful message. – grdl Nov 08 '17 at 15:24
  • Are you using a service worker? – Mackelito Mar 14 '19 at 10:41
  • what is the url value – kerbrose Oct 15 '19 at 08:28
  • for a quick mock api this one is very helpful (no CORS issues) - https://my-json-server.typicode.com/ – Adam Bielecki Mar 04 '20 at 15:09

26 Answers26

134

The problem was related to CORS. I noticed that there was another error in Chrome console:

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. The response had HTTP status code 422.`

This means the response from backend server was missing Access-Control-Allow-Origin header even though backend nginx was configured to add those headers to the responses with add_header directive.

However, this directive only adds headers when response code is 20X or 30X. On error responses the headers were missing. I needed to use always parameter to make sure header is added regardless of the response code:

add_header 'Access-Control-Allow-Origin' 'http://localhost:4200' always;

Once the backend was correctly configured I could access actual error message in Angular code.

grdl
  • 3,640
  • 3
  • 21
  • 25
  • also the following link can be helpful for enabling CORS: https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/enabling-cross-origin-requests-in-web-api – Bob Mar 25 '18 at 09:35
  • 24
    where should this line be added? – Omid Ataollahi Jul 15 '19 at 15:56
  • 1
    how do you add 'always' to an express.js .use function? Typically the structure is: app.use(function(req, res, next) { res.header("Access-Control-Allow-Origin", "http://localhost:4200"); … }); As you can see the res.header allows for two parameters... a control string and a value. I have tried to add 'always' in various ways but they all seem to fail. Any suggestions? – AppDreamer Oct 10 '19 at 18:38
  • 2
    @grdl, where the line add_header should be added? – sattva_venu Jan 26 '20 at 12:53
  • where add this line? I use php for my api – Mustafa UYSAL May 29 '20 at 07:32
  • 2
    The `add_header` line needs to be added to the configuration of Nginx server which serves the backend. Please mind that this is Nginx specific config. If you're using a different server you need to find its own way to ensure the `Access-Control-Allow-Origin` header is added. – grdl May 30 '20 at 07:54
  • 1
    if you are using express, you have to add it as middleware to the express server. more info here https://enable-cors.org/server_expressjs.html – Wilfredo Feb 24 '21 at 15:58
  • what if I use php, where can I add this line – Angelus Roman Aug 18 '21 at 07:38
  • Further to the answer above, add the following CORS configuration file to your server, and the issue will be resolved. – Krithika Apr 28 '22 at 07:37
42

In case anyone else ends up as lost as I was... My issues were NOT due to CORS (I have full control of the server(s) and CORS was configured correctly!).

My issue was because I am using Android platform level 28 which disables cleartext network communications by default and I was trying to develop the app which points at my laptop's IP (which is running the API server). The API base URL is something like http://[LAPTOP_IP]:8081. Since it's not https, android webview completely blocks the network xfer between the phone/emulator and the server on my laptop. In order to fix this:

Add a network security config

New file in project: resources/android/xml/network_security_config.xml

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
  <!-- Set application-wide security config -->
  <base-config cleartextTrafficPermitted="true"/>
</network-security-config>

NOTE: This should be used carefully as it will allow all cleartext from your app (nothing forced to use https). You can restrict it further if you wish.

Reference the config in main config.xml

<platform name="android">
    ...
    <edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application" xmlns:android="http://schemas.android.com/apk/res/android">
        <application android:networkSecurityConfig="@xml/network_security_config" />
    </edit-config>
    <resource-file src="resources/android/xml/network_security_config.xml" target="app/src/main/res/xml/network_security_config.xml" />
    ....
</platform>

That's it! From there I rebuilt the APK and the app was now able to communicate from both the emulator and phone.

More info on network sec: https://developer.android.com/training/articles/security-config.html#CleartextTrafficPermitted

haggy
  • 733
  • 6
  • 11
  • 1
    Thank a ton! I was also using an "http" url. Changed it to "https" and it worked. Btw, just changing a url to https won't work, you need a certificate to handle that. The server I was using supports both, so it was easier for me. Anyways, Thanks a Ton! – Xonshiz Jul 19 '19 at 13:11
  • 2
    yes...for me it is about cleartext too....because i'm using `http`.. it would no be problem if i use `https`....but in case i still want to use `http`, i directly add `android:usesCleartextTraffic="true"` in `application` tag in `AndroidManifest.xml` ...and it's working....thanks for mention about `cleartext`... – Syamsoul Azrien Jul 27 '19 at 12:19
  • How can I enable this in Spring boot? I am sorry if the question is too trivial but I am a beginner and I can't find any solutions online – Asma Rahim Ali Jafri Sep 23 '19 at 06:12
  • 1
    Thats brilliant mate, this just solved mine problem as well, thank you. :) – Roberto Capelo Nov 14 '20 at 20:59
  • Thank you very much ! – Guillaume Martin Jan 28 '22 at 16:46
19

If you are using .NET Core application, this solution might help!

Moreover this might not be an Angular or other request error in your front end application

First, you have to add the Microsoft CORS Nuget package:

Install-Package Microsoft.AspNetCore.Cors

You then need to add the CORS services in your startup.cs. In your ConfigureServices method you should have something similar to the following:

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors();
}

Next, add the CORS middleware to your app. In your startup.cs you should have a Configure method. You need to have it similar to this:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, 
ILoggerFactory loggerFactory)
{
    app.UseCors( options => 
    options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
    app.UseMvc();
}

The options lambda is a fluent API so you can add/remove any extra options you need. You can actually use the option “AllowAnyOrigin” to accept any domain, but I highly recommend you do not do this as it opens up cross origin calls from anyone. You can also limit cross origin calls to their HTTP Method (GET/PUT/POST etc), so you can only expose GET calls cross domain etc.

Feasoron
  • 3,471
  • 3
  • 23
  • 34
sathish
  • 300
  • 3
  • 14
18

working for me after turn off ads block extension in chrome, this error sometime appear because something that block http in browser

enter image description here

Dwiyi
  • 638
  • 7
  • 17
  • 1
    for me it was uBlock Origin which blocked downloading file with 'analytics' in it's name – marke Nov 27 '19 at 12:21
7

For me it was caused by a server side JsonSerializerException.

An unhandled exception has occurred while executing the request Newtonsoft.Json.JsonSerializationException: Self referencing loop detected with type ...

The client said:

POST http://localhost:61495/api/Action net::ERR_INCOMPLETE_CHUNKED_ENCODING
ERROR HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: null, ok: false, …}

Making the response type simpler by eliminating the loops solved the problem.

Perrier
  • 2,753
  • 5
  • 33
  • 53
5

This error was occurring for me in Firefox but not Chrome while developing locally, and it turned out to be caused by Firefox not trusting my local API's ssl certificate (which is not valid, but I had added it to my local cert store, which let chrome trust it but not ff). Navigating to the API directly and adding an exception in Firefox fixed the issue.

frax
  • 443
  • 4
  • 10
  • 1
    I have gone through *several* CORS answers and one after another each one did not provide a solution when using Firefox. I looked at this post and thought, "no way this is it but I'm out of ideas what the hell" and sure enough it worked. Thank you so much! – Aaron Jordan Dec 28 '18 at 23:54
  • @frax, I had exactly the same case! Thanks! :) – Marek Woźniak Jan 13 '19 at 18:15
5

If this is a node service, try the steps outlined here

Basically, it's a Cross-Origin Resource Sharing (CORS) error. More information about such errors here.

Once I updated my node service with the following lines it worked:

let express = require("express");
let app = express();

app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");    
    next();
  });
FistOfFury
  • 6,735
  • 7
  • 49
  • 57
4

A similar error can occur, when you didn't give a valid client certificate and token that your server understands:

Error:

Http failure response for (unknown url): 0 Unknown Error

Example code:

import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, map } from 'rxjs/operators';

class MyCls1 {

  constructor(private http: HttpClient) {
  }

  public myFunc(): void {

    let http: HttpClient;

    http.get(
      'https://www.example.com/mypage',
      {
        headers:
          new HttpHeaders(
            {
              'Content-Type': 'application/json',
              'X-Requested-With': 'XMLHttpRequest',
              'MyClientCert': '',        // This is empty
              'MyToken': ''              // This is empty
            }
          )
      }
    ).pipe( map(res => res), catchError(err => throwError(err)) );
  }

}

Note that both MyClientCert & MyToken are empty strings, hence the error.
MyClientCert & MyToken can be any name that your server understands.

Manohar Reddy Poreddy
  • 25,399
  • 9
  • 157
  • 140
  • i use this code in my ionic app . my ionic app used as index in my site. but this tricks cant help me . seems my apis in laravel need configuration maybe in ngnix or laravel or my docker host... i used cors middleware for cors enabled and it worked on my local with http but when deployed on docker cant call my api with https – saber tabatabaee yazdi May 17 '19 at 16:23
  • when i call my rest apis from http those worked but when call https they didnt respond to my clients. and return Mixed Type error. i think there are certificate error or something like nginx configuration or .htaccess because i add cors middleware for cors and all things worked good without https. my client hosted on http call http result is ok . but when my client host on https and call https errors happened – saber tabatabaee yazdi May 18 '19 at 07:00
  • Ok, one solution is, go to the https:// url that you have, and click on the lock icon beside the https, download the certificate to a file, read that file via import/require/fs, then give/pass that certificate string to the call to the url, then it will work. – Manohar Reddy Poreddy May 18 '19 at 07:27
  • is there any way to catch "err" in app to handle this error? – Dave Lee Jan 18 '23 at 19:04
4

I was getting that exact message whenever my requests took more than 2 minutes to finish. The browser would disconnect from the request, but the request on the backend continued until it was finished. The server (ASP.NET Web API in my case) wouldn't detect the disconnect.

After an entire day searching, I finally found this answer, explaining that if you use the proxy config, it has a default timeout of 120 seconds (or 2 minutes).

So, you can edit your proxy configuration and set it to whatever you need:

{
  "/api": {
    "target": "http://localhost:3000",
    "secure": false,
    "timeout": 6000000
  }
}

Now, I was using agentkeepalive to make it work with NTLM authentication, and didn't know that the agent's timeout has nothing to do with the proxy's timeout, so both have to be set. It took me a while to realize that, so here's an example:

const Agent = require('agentkeepalive');

module.exports = {
    '/api/': {
        target: 'http://localhost:3000',
        secure: false,
        timeout: 6000000,          // <-- this is needed as well
        agent: new Agent({
            maxSockets: 100,
            keepAlive: true,
            maxFreeSockets: 10,
            keepAliveMsecs: 100000,
            timeout: 6000000,      // <-- this is for the agentkeepalive
            freeSocketTimeout: 90000
        }),
        onProxyRes: proxyRes => {
            let key = 'www-authenticate';
            proxyRes.headers[key] = proxyRes.headers[key] &&
                proxyRes.headers[key].split(',');
        }
    }
};
Marcos Dimitrio
  • 6,651
  • 5
  • 38
  • 62
2

I'm using ASP.NET SPA Extensions which creates me a proxy on ports 5000 and 5001 that pass through to Angular's port 4200 during development.

I had had CORS correctly setup for https port 5001 and everything was fine, but I inadvertently went to an old bookmark which was for port 5000. Then suddenly this message arose. As others have said in the console there was a 'preflight' error message.

So regardless of your environment, if you're using CORS make sure you have all ports specified - as the host and port both matter.

Simon_Weaver
  • 140,023
  • 84
  • 646
  • 689
2

For me it was a browser issue, since my requests were working fine in Postman.

Turns out that for some reason, Firefox and Chrome blocked requests going to port 6000, once I changed the ASP.NET API port to 4000, the error changed to a known CORS error which I could fix.

Chrome at least showed me ERR_UNSAFE_PORT which gave me a clue about what could be wrong.

Shahin Dohan
  • 6,149
  • 3
  • 41
  • 58
1

If you are using Laravel as your Backend, then edit your .htaccess file by just pasting this code, to solve problem CROS in your Angular or IONIC project

Header add Access-Control-Allow-Origin "*"
Header add Access-Control-Allow-Methods: "GET,POST,OPTIONS,DELETE,PUT"
  • 7
    You should never ever allow "*"! In general you know who is talking to your backend and you should set their host explicitly. – itmuckel Feb 19 '18 at 10:24
  • @itmuckel but if you are doing an app for android the host it's not known. Will be every mobile that consume your service, am I right? – Martin Jun 24 '18 at 23:47
  • 2
    we needed to use cordova-plugin-advanced-http and the @ionic/native wrapper to have http calls from the device natively instead of using a browser-based ajax call. @Martin – user323774 Aug 30 '18 at 22:07
1

If you have a proper cors header in place. Your corporate network may be stripping off the cors header. If the website is externally accessible, try accessing it from outside your network to verify whether the network is causing the problem--a good idea regardless of the cause.

N-ate
  • 6,051
  • 2
  • 40
  • 48
1

Add This Codes in your connection file

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: PUT,GET,POST,DELETE");
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");
1

if you are using nodejs as backend, here are steps to follow

  1. install cors in your backend app

    npm install cors

  2. Add this code

     const cors = require('cors');
     const express = require('express');
     const expressApp = express();
     expressApp.use(cors({
         origin: ['http://localhost:4200'],
         "methods": "GET,PUT,POST",
         "preflightContinue": false,
         "optionsSuccessStatus": 204,
         credentials: true
     }));
    
YouBee
  • 1,981
  • 1
  • 15
  • 16
1

In my case UseCors was placed after UseAuthentication / Authorization: No 'Access-Control-Allow-Origin' header is present on the requested resource when 401 response is returned from the server

Snaketec
  • 471
  • 2
  • 14
0

Is not as old as other questions, but I just struggled with this in an Ionic-Laravel app, and nothing works from here (and other posts), so I installed https://github.com/barryvdh/laravel-cors complement in Laravel and started and it works pretty well.

0

Mine was caused by an invalid relationship in the models I was trying to query. Figured out by debugging the response it crashed at the relation.

J.Kirk.
  • 943
  • 3
  • 12
  • 32
0

For me it wasn't an angular problem. Was a field of type DateTime in the DB that has a value of (0000-00-00) and my model cannot bind that property correct so I changed to a valid value like (2019-08-12).

I'm using .net core, OData v4 and MySql (EF pomelo connector)

Luis Lopez
  • 561
  • 1
  • 10
  • 29
0

In asp.net core, If your api controller doesn't have annotation called [AllowAnonymous], add it to above your controller name like

[ApiController]
    [Route("api/")]
    [AllowAnonymous]
    public class TestController : ControllerBase
dgncn
  • 49
  • 5
0

You must use --port when serve server ng serve --open --port 4200

    export class DatabaseService {
  baseUrl: String = "http://localhost:8080/";
  constructor(private http: HttpClient) { }


  saveTutorial(response) {
    var fullUrl = this.baseUrl + "api/tutorials";
   
    return this.http.post(fullUrl,response);
  }
}
Wai Yan Moung
  • 239
  • 2
  • 5
0

I had the same issue. I used grdl's answer above and added a cors configuration to my server like the one below and the problem was solved.

{
"cors": [
    {
      "origin": [“*”],
      "method": ["GET"],
      "responseHeader": ["Content-Type"],
      "maxAgeSeconds": 3600
    }
  ]
}

Look at the specific cors config help for your server to see how to set it up.

Krithika
  • 115
  • 1
  • 10
0

2022-07-13

This is the easiest way but DON'T with PROD.

Inside index.html, add or edit the existing <meta http-equiv="Content-Security-Policy" content=". For example CORS blocked my access to local IIS Express https://localhost:44387/api/test, solution is have this

<meta http-equiv="Content-Security-Policy" content="
...
connect-src 'self' https://localhost:44387 https://anysite.com ...">
Jeb50
  • 6,272
  • 6
  • 49
  • 87
0

Let do some simple ones:

a) Network is disconnected - zero byte response.

b) I get this when I cancel a http call (yes you can do that)

c) During start up when I move pages too quickly it will cancel http calls because angular has not hooked up properly. I locked page to stop this one occurring.

d) We had a proxy in the middle and it terminated the connection after 30 seconds rather sending a HTTP timeout packet. If you look at the .net logs on back end you will see a client disconnected message. (these are not unusual as a user may just close their browser)

All of these have happened to me and I have no idea how to separate out which cause it is for any specific failure.

KenF
  • 544
  • 4
  • 14
0

I stumbled on the same error when connecting my Angular front end with Django REST API backend. The problem was simply not having installed cors headers. This can be fixed by

  1. Installing django-cors-headers. Do this by using pip

    pip install django-cors-headers

  2. Adding cors-headers to installed apps in /settings.py

INSTALLED_APPS = [ 'rest_framework', 'corsheaders' ]

  1. At the whatever line in your code, add this:

    CORS_ALLOW_ALL_ORIGINS =True

This fixed my issue. Hope it will be helpful to you.

Happy coding dev

-2

My error was that the file was too large (dotnet core seems to have a limit @~25Mb). Setting

  • maxAllowedContentLength to 4294967295 (max value of uint) in web.config
  • decorating the controller action with [DisableRequestSizeLimit]
  • services.Configure(options => { options.MultipartBodyLengthLimit = 4294967295; }); in Startup.cs

solved the problem for me.

Spikolynn
  • 4,067
  • 2
  • 37
  • 44