Skip to content

Search is only available in production builds. Try building and previewing the site to test it out locally.

CORS Troubleshooting

This guide covers CORS configuration, common errors, debugging techniques, browser network inspection, and production patterns for Adobe Commerce Storefronts.

CORS configuration

If using a CORS module with admin UI configuration (such as graycore/magento2-cors), navigate to StoresConfigurationGeneralWebCORS Whitelist in the Adobe Commerce admin panel.

The following configuration options are typically available.

Allowed Origins

Add your storefront URLs, one per line (no trailing slashes):

http://localhost:3000
http://localhost:5173
https://staging-storefront.example.com
https://storefront.example.com

Allow Credentials

Enable this setting if your storefront needs to:

  • Send authentication cookies
  • Include session cookies
  • Send credentials with cross-origin requests

When enabled, the Access-Control-Allow-Credentials: true header will be sent.

Allowed Methods

Specify HTTP methods your storefront uses (comma-separated):

GET,POST,OPTIONS

Understanding preflight requests

Before sending the actual request, browsers send an OPTIONS request (called a “preflight”) to check if the cross-origin request is allowed. This happens automatically for requests with:

  • Custom headers (like Authorization)
  • Methods other than GET/POST/HEAD
  • Content-Type other than basic types

The OPTIONS request asks: “Can I send a POST request with these headers?” The server responds with allowed methods, headers, and origins.

Allowed Headers

Specify headers your storefront sends (comma-separated):

Content-Type,Authorization,X-Requested-With,Store

Common headers include:

  • Content-Type: For JSON requests
  • Authorization: For bearer tokens
  • Store: For multistore configurations
  • X-Requested-With: For AJAX requests

Common CORS errors

The following are standard CORS errors enforced by browser security policies. These error messages appear in the browser console (DevTools).

No ‘Access-Control-Allow-Origin’ header

Access to fetch at 'https://commerce.example.com/graphql' from origin 'http://localhost:3000'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the
requested resource.

Cause

CORS headers are not being sent by your Commerce backend. This could mean:

  • CORS support is not configured
  • The origin is not in the allowed list
  • The configuration cache needs to be cleared

Solution

  • Verify CORS is configured (via module, custom code, or server configuration)
  • Add your storefront origin to the allowed origins list
  • Clear the cache: php bin/magento cache:flush

Origin not allowed

Access to fetch at 'https://commerce.example.com/graphql' from origin 'http://localhost:3000'
has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value
'https://storefront.example.com' that is not equal to the supplied origin.

Cause

The requesting origin is not in the allowed origins list.

Solution

Add the exact origin (including protocol and port) to the Allowed Origins configuration.

Credentials flag issue

Access to fetch at 'https://commerce.example.com/graphql' from origin 'http://localhost:3000'
has been blocked by CORS policy: 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'.

Cause

You have Allow Credentials enabled but are using * for allowed origins.

Solution

Replace * with specific origins when credentials are required.

Common issues

If you encounter CORS errors after installing adobe-commerce/storefront-compatibility, verify that your CORS implementation is compatible with Adobe Commerce Storefronts. If using the graycore module, ensure v2.x or later is installed.

Debug checklist

Verify CORS is configured

If using a CORS module, check that it’s installed and enabled:

# List all enabled modules
php bin/magento module:status | grep -i cors

If using a custom CORS implementation, verify your code is deployed and active.

Verify CORS configuration

In your CORS configuration (admin panel, config files, or server configuration), confirm:

  • Your storefront origin is in the Allowed Origins list
  • Origins match exactly (including protocol and port)
  • No trailing slashes in origins
  • Allowed Methods includes OPTIONS
  • Allowed Headers includes headers your storefront sends

Inspect browser network traffic

Open DevTools → Network tab and look for:

Preflight OPTIONS request

Request URL: https://commerce.example.com/graphql
Request Method: OPTIONS

Expected response headers:

Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400

Actual GraphQL POST request

Request URL: https://commerce.example.com/graphql
Request Method: POST

Expected response headers:

Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Credentials: true

Check server logs

If CORS headers are present but requests still fail:

tail -f var/log/system.log
tail -f var/log/exception.log

Look for PHP errors, GraphQL exceptions, or module conflicts.

Clear all caches

After any configuration changes:

php bin/magento cache:flush
php bin/magento cache:clean

Some CORS configurations may also be cached in Varnish/Fastly if applicable.

Distinguishing CORS errors from server-side errors

When debugging, it’s important to distinguish CORS policy failures from server-side GraphQL exceptions. Here’s an example of a server-side error that might be mistaken for a CORS issue:

{
"message": "Internal server error",
"extensions": {
"debugMessage": "Magento\\InventoryConfiguration\\Model\\IsSourceItemManagementAllowedForProductType\\Interceptor::execute(): Argument #1 ($productType) must be of type string, null given"
}
}

This indicates a PHP/GraphQL issue (inventory configuration or compatibility) and not a missing Access-Control-Allow-Origin header.

Edge cases and special scenarios

Docker and containerized environments

When running Commerce in Docker, you may need to add multiple origin variations:

http://localhost:3000
http://127.0.0.1:3000
http://host.docker.internal:3000

Multiple storefronts

For multiple storefronts accessing the same Commerce backend, add each origin separately:

https://storefront-us.example.com
https://storefront-eu.example.com
https://storefront-asia.example.com

Each storefront is treated as a separate origin and must be explicitly allowed.

Adobe Commerce Cloud vs on-premise

Adobe Commerce Cloud

  • CORS configuration works the same way
  • Ensure the module is installed in your environment
  • Configuration syncs across Cloud environments through standard config management

On-premise

  • No differences in the CORS setup
  • You have full control over all infrastructure

Production best practices

The recommended production approach is to avoid CORS entirely by serving both the storefront and the backend from the same domain using a CDN proxy.

Serve both your storefront and Commerce backend from the same domain:

  • Storefront: https://example.com → CDN serves static assets
  • GraphQL API: https://example.com/graphql → CDN proxies to Commerce backend

This requires configuring your CDN to proxy /graphql requests to your Commerce backend.

Benefits:

  • No CORS complexity
  • Better performance (fewer preflight requests)
  • Simpler security model
  • Better caching control

Implementation approaches:

  1. Fastly VCL routing: Configure Fastly to route GraphQL requests to your Commerce backend using VCL (Varnish Configuration Language). The VCL detects requests to /graphql and proxies them to your backend origin while serving other requests from your storefront origin.

  2. Cloudflare Workers / CDN Edge Functions: Use edge functions to route API requests to your backend dynamically.

  3. Reverse proxy (Nginx/Apache): Configure your web server to proxy /graphql requests to the backend.

Note: This approach requires CDN/infrastructure expertise. If you don’t have these resources, use CORS configuration instead.

CORS configuration

If you must use different domains (for example, storefront.example.comcommerce.example.com), use CORS configuration. Use specific allowed origins for single production domains, or a wildcard * when you have multiple dynamic preview URLs (such as Edge Delivery Services branch previews).

References

CORS standards and specifications

Adobe Commerce

Additional tools and platforms