CORS Error Messages

The error messages listed below all come from Chrome. For more information about CORS error messages in Firefox see developer.mozilla.org.

The first line of a CORS error in Chrome will typically look something like this:

Access to XMLHttpRequest at 'http://localhost:3000/api' from origin 'http://localhost:8080' has been blocked by CORS policy:

The exact form of the message will depend on the request you're attempting.

Requests initiated using fetch will start Access to fetch instead of Access to XMLHttpRequest. The URL http://localhost:3000/api will be the URL of the cross-origin resource you tried to access. The origin, http://localhost:8080, will be the origin of the current page. Usually that'll be the first part of the URL in your browser's address bar.

If the request you're attempting uses HTTP redirects then you may get a longer version of this opening line:

Access to XMLHttpRequest at 'http://localhost:3000/new-api' (redirected from 'http://localhost:3000/old-api') from origin 'http://localhost:8080' has been blocked by CORS policy:

When using redirects, all the requests must successfully pass the CORS checks. The error message indicates the initial URL as well as the URL that failed. The initial request, and any intermediate redirects, must have passed the CORS checks or the final request wouldn't have even been attempted.

Generally it is the next part of the error message that reveals why the request failed the CORS check. Those messages are listed below.

If you want to see how the Chrome error messages are built take a look at the source code (not as scary as it sounds) at cs.chromium.org.

#
No 'Access-Control-Allow-Origin' header is present on the requested resource.

This error indicates that the server response did not include the header Access-Control-Allow-Origin.

This is very similar to another error message. That error relates to the preflight OPTIONS request, whereas this error specifically concerns the main request.

If you’re new to CORS see What is CORS? for more information.

If you’ve attempted to configure the CORS headers but you’re still seeing this message then try I’ve configured my server to include CORS headers but they still aren’t showing up. Why?.

If you are making the request using the fetch API then you’ll also see the following text at the end of the error message:

If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

For more information about opaque responses see What is an opaque response?. Using an opaque response will suppress the error message but it won’t allow you to access the response details.

#
The 'Access-Control-Allow-Origin' header has a value 'http://example.com' that is not equal to the supplied origin.

This error indicates that the server response did include the header Access-Control-Allow-Origin but it was set to the wrong value. For a request to succeed Access-Control-Allow-Origin must either be * or an exact match for the Origin request header.

If you are making the request using the fetch API then you’ll also see the following text at the end of the error message:

Have the server send the header with a valid value, or, if an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

For more information about opaque responses see What is an opaque response?. Using an opaque response will suppress the error message but it won’t allow you to access the response details.

#
The 'Access-Control-Allow-Origin' header contains multiple values 'http://example.com, http://localhost:8080', but only one is allowed.

Many HTTP headers support multiple values separated by commas. Access-Control-Allow-Origin does not. It must either be the special value * or an exact match for the Origin request header.

Usually the cause of this problem is that the header value is being set twice. If any header appears twice on the response then the HTTP specification says it should be treated as equivalent to a single header that has the values separated using a comma followed by a space. Browsers, proxies and some servers will often combined multiple headers in this way.

So, for example, you would see the error above if the server returned the following headers:

Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Origin: http://localhost:8080

When these headers reach the browser they will be combined to form:

Access-Control-Allow-Origin: http://example.com, http://localhost:8080

The underlying cause for this problem may be that the CORS headers are being added in multiple places. For example, it may be that a CORS plugin has been added twice. Or perhaps an intermediate web server is also configured to add the CORS headers.

A particularly common version of this message is:

The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed.

It is very unlikely that the header was actually set to *, *. Much more likely is that it has been added twice:

Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: *

If you are making the request using the fetch API then you’ll also see the following text at the end of the error message:

Have the server send the header with a valid value, or, if an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

For more information about opaque responses see What is an opaque response?. Using an opaque response will suppress the error message but it won’t allow you to access the response details.

#
The 'Access-Control-Allow-Origin' header contains the invalid value 'xyz'.

This error indicates that the server response did include the header Access-Control-Allow-Origin but it contained an invalid value. Here invalid doesn’t just mean that it doesn’t match the requested Origin but, more than that, it doesn’t appear to even be a valid origin value. Origin values should parse as valid URIs.

Some examples of values that will give this error:

xyz
example.com
http://example.com:67890

The last example only fails because the port number is too large to be valid.

This message is intended to provide extra feedback to the developer but ultimately it isn’t really a separate case. The Origin request header will always be well-formed so if the Access-Control-Allow-Origin header can’t be parsed it can’t be a match.

This is very similar to another error message. That error relates to the preflight OPTIONS request, whereas this error specifically concerns the main request.

If you are making the request using the fetch API then you’ll also see the following text at the end of the error message:

Have the server send the header with a valid value, or, if an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

For more information about opaque responses see What is an opaque response?. Using an opaque response will suppress the error message but it won’t allow you to access the response details.

#
The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.

If the request is made using XMLHttpRequest, as opposed to fetch, then there’ll be an extra line at the end of this error:

The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

This error indicates that the Access-Control-Allow-Origin response header had the value *. Using a * wildcard is not allowed for requests that use withCredentials.

In many cases withCredentials isn’t required and can simply be removed. If you aren’t using cookies then you probably don’t need it. For more information see What is withCredentials? How do I enable it?.

If you do need withCredentials then you’ll have to change the server so that it doesn’t return * for Access-Control-Allow-Origin. Instead the server should check that the Origin request header contains an allowed origin before echoing that origin value back in Access-Control-Allow-Origin.

If you want to understand why this restriction on using * exists then see What are the security implications of CORS?. By extension it’s important that the server does not simply echo back all origins: only trusted origins should be allowed.

There are browser extensions that automatically set the Access-Control-Allow-Origin header to *, overriding any value set by the server. These tools can trigger the error message above, even if the server is returning all of the correct headers.

#
The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'.

If the request is made using XMLHttpRequest, as opposed to fetch, then there’ll be an extra line at the end of this error:

The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

For requests that use withCredentials the server response must include the header Access-Control-Allow-Credentials set to the value true.

If the message reports a value of '' then that usually means the header is missing altogether rather than being returned with an explicit empty value.

If the error message indicates that the current value is 'true, true' then that suggests that the header is being returned twice.

See also What is withCredentials? How do I enable it?.

#
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

This error indicates that the preflight OPTIONS request failed because the server did not include the response header Access-Control-Allow-Origin.

This is very similar to another error message. That error relates to the main request, whereas this error specifically concerns the preflight OPTIONS request.

If you’re new to CORS see What is CORS? for more information.

If you are unclear what a preflight OPTIONS request is then see What is a preflight request?.

If you’ve attempted to configure the CORS headers but you’re still seeing this message then try I’ve configured my server to include CORS headers but they still aren’t showing up. Why?.

If you are making the request using the fetch API then you’ll also see the following text at the end of the error message:

If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

For more information about opaque responses see What is an opaque response?. Using an opaque response will suppress the error message but it won’t allow you to access the response details.

#
Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value 'http://example.com' that is not equal to the supplied origin.

This error specifically refers to the preflight OPTIONS request but is otherwise identical to an earlier error message.

If you are unclear what a preflight OPTIONS request is then see What is a preflight request?.

#
Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header contains multiple values 'http://example.com, http://localhost:8080', but only one is allowed.

This error specifically refers to the preflight OPTIONS request but is otherwise identical to an earlier error message.

If you are unclear what a preflight OPTIONS request is then see What is a preflight request?.

#
Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header contains the invalid value 'xyz'.

This error specifically refers to the preflight OPTIONS request but is otherwise identical to an earlier error message.

If you are unclear what a preflight OPTIONS request is then see What is a preflight request?.

#
Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.

If the request is made using XMLHttpRequest, as opposed to fetch, then there’ll be an extra line at the end of this error:

The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

This error specifically refers to the preflight OPTIONS request but is otherwise identical to an earlier error message.

If you are unclear what a preflight OPTIONS request is then see What is a preflight request?.

#
Method PUT is not allowed by Access-Control-Allow-Methods in preflight response.

Any cross-origin request that uses a method other than GET, HEAD or POST will trigger a preflight request. The error message above refers to a PUT request but an equivalent message would be shown for other methods, such as DELETE.

The browser will automatically include a request header in the preflight request called Access-Control-Request-Method. The value specifies the method of the original request, e.g. Access-Control-Request-Method: PUT.

The server is expected to respond with a comma-separated list of acceptable request methods in the response header Access-Control-Allow-Methods. If the method in Access-Control-Request-Method is not included in that list it will trigger the error above.

Even when using the request methods GET, HEAD or POST a preflight can be triggered if there are custom request headers. In that case the browser will still include the Access-Control-Request-Method request header but the Access-Control-Allow-Methods response header will be ignored.

A value of * can also be used as a wildcard in Access-Control-Allow-Methods. However, this is not allowed when using withCredentials and will result in the same error message.

If you are unclear what a preflight OPTIONS request is then see What is a preflight request?.

#
Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.

While the example message above mentions content-type it could equally reference almost any request header.

When performing a preflight OPTIONS request the browser will automatically include a request header called Access-Control-Request-Headers. Its value will be a comma-separated list of the names of any custom header fields that have been set on the original request.

When the server responds to the preflight request it should include the response header Access-Control-Allow-Headers. This should list the custom header fields that the server is willing to allow.

If any of the custom headers listed in Access-Control-Request-Headers are not included in Access-Control-Allow-Headers then the preflight will fail, leading to the error shown above. The error will name the first header that was missing, though there may be others.

A value of * can also be used as a wildcard in Access-Control-Allow-Headers. However, this is not allowed when using withCredentials and will result in the same error message.


Related:

#
Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'.

If the request is made using XMLHttpRequest, as opposed to fetch, then there’ll be an extra line at the end of this error:

The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

For requests that use withCredentials the server response to the preflight OPTIONS request must include the header Access-Control-Allow-Credentials set to the value true. The same header must also be included for the main request, though omitting it would trigger a different error message.

If you are unclear what a preflight OPTIONS request is then see What is a preflight request?.

If the message reports a value of '' then that usually means the header is missing altogether rather than being returned with an explicit empty value.

If the error message indicates that the current value is 'true, true' then that suggests that the header is being returned twice.

See also What is withCredentials? How do I enable it?.

#
Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.

Quick fix: Make sure you’ve included the http:// or https:// at the start of the request URL.

The first part of a URI, prior to the colon, is known as the scheme. Some examples include:

https://www.google.com        -> https
file:///home/user/picture.png -> file
mailto:webmaster@example.com  -> mailto
javascript:return false;      -> javascript

Cross-origin requests can only be made to URIs with certain schemes, as indicated in the error message. For example, trying to access a file on the local filesystem using the file scheme is not allowed.

A common mistake is trying to use a URI of the form localhost:3000/api. The problem is that it doesn’t include the http:// or https:// prefix, so localhost is parsed as ‘the bit before the colon’, i.e. the scheme.

The Network tab of Chrome’s developer tools will not show requests that trigger this error.

#
Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.

For a preflight OPTIONS request to succeed the response status code must be in the range 200 to 299. Common choices are 200 and 204.

Several status codes in the range 300 to 399 can be used to attempt a redirect in conjunction with the Location header. This is allowed for the main request but not for the preflight. Attempting a redirect on the preflight will trigger the error above.

Even if you aren’t intentionally using redirects there are two common ways that they can creep in:

  1. Redirecting from http to https.
  2. Redirecting to add or remove a trailing URL slash. e.g. A server may redirect http://example.com/api/users to http://example.com/api/users/ or vice-versa.

If you’re unsure why a redirect is occurring then the first step is to check the Location response header. Often the new location will only differ from the original location by a single character so you may need to check it very carefully. Safari and recent versions of Chrome don’t show the preflight request separately in the Network tab of the developer tools, making it difficult to check the response headers. See Why can’t I access the response headers in Chrome’s developer tools? for more information.

While the server should not be attempting to redirect the preflight OPTIONS request it is usually trivial to fix in the client by updating the URL to avoid the redirect altogether.


Related:

#
Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

For a preflight OPTIONS request to succeed the response status code must be in the range 200 to 299. Common choices are 200 and 204.

Any other status code will cause the preflight check to fail. That includes attempts at authentication using a 401 status code. If you have a server-side authorization layer you’ll need to ensure it doesn’t interfere with preflight requests.

The best place to start with debugging this error is to check which status code is coming back. There may also be a response body that provides further information.

This can be tricky in browsers that don’t show the preflight OPTIONS request separately in the developer tools. See Why can’t I access the response headers in Chrome’s developer tools? for more information.

The other thing to check is the request URL. Specifically check in the developer tools rather than in your code. Make sure the URL really is what you intended. Depending on how the server is configured there are several different status codes you might receive if the URL is wrong.

Attempts to redirect to a different URL will typically show a different error message. See Redirect is not allowed for a preflight request.

#
Redirect location '' contains a username and password, which is disallowed for cross-origin requests.

An old feature of URLs allows them to include a username and password near the beginning. e.g.:

http://admin:password123@example.com/

The use of this form of authentication is discouraged and support is somewhat limited.

If a server attempts to redirect a CORS request to a URL that contains this form of username and password then the request will fail.

Typically the server will have returned a status code of 301, 302, 307 or 308 and the rejected URL will have been specified in the Location response header.

You can suggest improvements to this page via GitHub.