Learning path · Level 7 · Tutorial 4

Diagnose Request Failures and CORS Restrictions

Investigate browser request failures by checking origins, the Network panel, and console messages. Determine which problems your client code can fix and which require changes from the API owner, without disabling browser protections.

  • Level: Intermediate
  • Duration: 20 min
  • 8 steps
Start tutorial Back to the path
Diagnose Request Failures and CORS Restrictions

What you will go through

  1. Compare Origins Before Diagnosing Classify HTTP(S) URLs by comparing their scheme, hostname, and effective port before investigating a request problem. 2 min
  2. Separate Sending from Reading See CORS as a browser decision about exposing a cross-origin response to JavaScript, while keeping request sending, response receipt, and JavaScript access distinct. 2 min
  3. Read the Preflight Exchange Examine a CORS preflight, identify the distinct permission checks, and distinguish a denied preflight from an actual request whose response is blocked from JavaScript. 3 min
  4. Collect Evidence in Your Browser Create a safe local GET diagnostic and capture the page origin, request details, Network evidence, Console evidence, and JavaScript outcome. 3 min
  5. Distinguish the Failure Categories Use browser and JavaScript evidence together to distinguish HTTP errors, connectivity failures, mixed-content blocks, and CORS restrictions. 3 min
  6. Reject Browser-Only CORS Workarounds Reject client-side CORS bypasses and use normal browser request behavior while recognizing that readable access still depends on API-server permission. 2 min
  7. Choose the Next Action and Owner Choose safe next actions from browser evidence and identify whether the client developer or API owner is responsible. 2 min
  8. Complete a Request-Failure Diagnosis Integrate origin comparison, browser evidence, failure classification, and ownership decisions into a complete request-failure diagnosis. 3 min

What you will learn

  • Determine whether two URLs have the same origin.
  • Explain why a cross-origin JSON request may trigger a preflight.
  • Use request and console evidence to distinguish an HTTP error from a blocked or failed request.
  • Explain why no-cors and client-authored permission headers cannot bypass CORS restrictions.
  • Identify a next action without assuming that an unreadable response means the server received nothing.

Before you start

  • Fetch and Validate JSON Responses
  • Send JSON Data with HTTP Requests

Step 1 of 8

Compare Origins Before Diagnosing

Classify HTTP(S) URLs by comparing their scheme, hostname, and effective port before investigating a request problem.

Identify the origin components

The three-part origin

An HTTP(S) origin has exactly three parts: scheme + hostname + effective port. Compare those parts to decide whether two URLs are same-origin or cross-origin.

Everything after the port—path, query string, and fragment—can identify a resource, but it does not change the origin.

URL anatomy

A diagram separates a URL into scheme, hostname, effective port, and the remaining path, query, and fragment. Only the first three parts are grouped as the origin.

Compare scheme, hostname, and effective port—not the rest of the URL.

Normalize before you compare

Use the effective port

A port that is omitted still has an effective value: HTTPS uses port 443 and HTTP uses port 80 by default. Normalize default ports before comparing.

For example, https://app.example.test:443 and https://app.example.test have the same origin. In contrast, a Vite page at http://localhost:5173 and a URL at http://localhost:3000/products are cross-origin because their effective ports differ.

Normalization examples

The origin is shown in normalized form, without its default port.

A URL can change without changing its origin.
URLNormalized originComparison note
https://app.example.test/products?sort=name#tophttps://app.example.testPath, query, and fragment ignored
https://app.example.test:443/productshttps://app.example.test443 is the HTTPS default
http://app.example.test:80/productshttp://app.example.test80 is the HTTP default
http://localhost:5173/productshttp://localhost:51735173 is part of the origin

Example

localhost and 127.0.0.1 are different hostnames. Even when they use the same scheme and port, changing between them creates a cross-origin pair.

Practice: compare URL pairs

Classify the pairs

Match each URL pair to its origin classification and the component that matters.

Tap an item and then its matching pair.

Step 2 of 8

Separate Sending from Reading

See CORS as a browser decision about exposing a cross-origin response to JavaScript, while keeping request sending, response receipt, and JavaScript access distinct.

The browser is the access checkpoint

CORS controls readable access

A cross-origin request crosses an important boundary: browser JavaScript is not automatically allowed to read the response.

For a request from https://app.example.test to https://api.example.test/products, the browser applies the same-origin policy. The API server must grant CORS permission before the browser exposes that cross-origin response to the page's JavaScript.

This is about access to the response—not a promise that the request was never sent.

Where the browser applies CORS

Diagram showing Browser JavaScript, Browser, and API server. The browser sends a cross-origin GET with an Origin header and decides whether to expose the returned response to JavaScript.

The browser can receive a response while keeping it unavailable to Browser JavaScript.

The server grants the page origin

Read the permission in the right direction

In these cross-origin fetch() examples, the browser supplies an Origin request header that identifies the page making the request.

The API can grant permission with the response header Access-Control-Allow-Origin. Its value must identify the requesting page origin.

For example, a page at https://app.example.test needs a response permission value for https://app.example.test—not https://api.example.test, which is the API's own origin.

Example

Example: permission names the page

A Product Catalog page runs this cross-origin request:

const response = await fetch('https://api.example.test/products');

The browser supplies these request details:

Request headers

Origin: https://app.example.test

If the API response includes:

Response headers

Access-Control-Allow-Origin: https://app.example.test

then the browser may expose the response to the page's JavaScript. The permission names the page that is allowed to read, not the API server.

Do not equate blocked reading with unsent work

Three events, not one

Keep these events separate when diagnosing a cross-origin GET:

  1. Sending: the browser sends the request.
  2. Receiving: the API may receive it and send a response back.
  3. Exposing: the browser decides whether Browser JavaScript may inspect that response.

A simple cross-origin GET can reach the API even when the response lacks CORS permission. In that case, JavaScript cannot read the response, but that alone does not prove the API received nothing.

Later, use Network and Console evidence to investigate what happened; do not infer server receipt from JavaScript access alone.

Tip

Diagnostic mindset

For a response that does not include a suitable Access-Control-Allow-Origin value, the browser withholds that cross-origin response from page JavaScript. The missing permission is about what JavaScript may read after the exchange, not proof that the API never handled the GET.

Practice: separate receipt from readable access

Interpret the exchange

Diagram of a GET request sent from the browser to an API server, an HTTP response returning to the browser, and a blocked boundary before Browser JavaScript because the response lacks Access-Control-Allow-Origin.

Use the request and response path shown to choose the most accurate conclusion.

Diagnose the visible exchange

Based on the diagram, which conclusion is best supported?

Step 3 of 8

Read the Preflight Exchange

Examine a CORS preflight, identify the distinct permission checks, and distinguish a denied preflight from an actual request whose response is blocked from JavaScript.

Recognize a preflight-triggering request

When the Browser asks first

A preflight is a browser-generated OPTIONS request that asks permission before a cross-origin actual request. The Browser sends it when the proposed request has features outside the CORS safelist.

A cross-origin POST with Content-Type: application/json triggers preflight because application/json is not a CORS-safelisted media type. POST itself is a CORS-safelisted method; the non-safelisted request header is what requires this check.

JSON-looking body text alone is not the trigger. The configured Content-Type matters. Cross-origin PUT and DELETE also trigger preflight because those methods are not CORS-safelisted.

A preflight comes before the proposed request

Flow diagram showing Browser JavaScript proposing a JSON POST, the Browser sending an OPTIONS preflight to an API server, and a conditional actual POST afterward.

For a preflight-triggering request, the Browser evaluates permission before it sends the actual request.

Proposed Product Catalog request

This cross-origin Product Catalog request has a non-safelisted Content-Type, so the Browser preflights it.

javascript
const requestUrl = 'https://api.example.test/products';

const response = await fetch(requestUrl, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ name: 'Notebook' })
});

Check what the API authorized

Read each permission by its role

The preflight tells the API what the Browser proposes to send. The API must return the permissions relevant to that proposal. A successful OPTIONS status alone does not establish permission.

For a JSON POST, the Browser needs an allowed requesting origin and permission for the non-safelisted Content-Type header. For a PUT or DELETE, it also checks permission for that non-safelisted method.

What the preflight exchanges say

Illustrative excerpts for a page at https://app.example.test requesting https://api.example.test/products.

Request headers describe the proposal. Response headers grant separate permissions needed for that proposal.
ExchangeHeader excerptRole
Request headersOrigin: https://app.example.testIdentifies the requesting page origin
Request headersAccess-Control-Request-Method: POSTStates the proposed method
Request headersAccess-Control-Request-Headers: content-typeStates the non-safelisted requested header
Response headersAccess-Control-Allow-Origin: https://app.example.testPermits this requesting page origin
Response headersAccess-Control-Allow-Headers: Content-TypePermits the JSON POST request header
Response headersAccess-Control-Allow-Methods: PUT, DELETEPermits those non-safelisted methods

Tip

Status is not permission

An OPTIONS response with HTTP 204 can still fail preflight when its permission headers do not authorize the needed origin, method, or requested headers.

The Browser can reuse a previously granted preflight permission. Therefore, no new OPTIONS entry in Network does not prove that a request had no preflight requirements.

Distinguish denial from a blocked actual response

Separate the two Browser decisions

A failed preflight stops the actual request for that attempt. For example, a JSON POST can be denied when the preflight response does not allow the requested Content-Type header. A PUT can be denied when the response does not allow PUT in Access-Control-Allow-Methods.

When preflight succeeds, the Browser sends the actual request. That actual response must still provide suitable CORS permission before Browser JavaScript can read it.

Two different outcomes

Use Network and Console evidence together before making a claim about server receipt.

The absence or presence of the actual request changes what the evidence supports.
Evidence patternJavaScript outcomeSupported conclusion
JSON POST preflight lacks Access-Control-Allow-Headers for Content-Type; no actual POST appearsfetch rejects; no readable ResponseThe Browser withheld the actual POST for this attempt
PUT preflight lacks PUT in Access-Control-Allow-Methods; no actual PUT appearsfetch rejects; no readable ResponseThe Browser withheld the actual PUT for this attempt
Preflight permits JSON POST; actual POST appears; actual response lacks Access-Control-Allow-Originfetch rejects; no readable ResponseThe POST may have reached the API, but JavaScript cannot read its response

Warning

Treat server receipt carefully

Do not conclude “the server received nothing” merely because fetch() gives no readable response. That conclusion is supported when a failed preflight withheld the actual request. It is not supported when Network shows that the actual request was sent and only its response was blocked from Browser JavaScript.

Practice the permission roles

Match permission headers to roles

Match each response header to the permission it provides.

Tap an item and then its matching pair.

Practice the exchange sequence

Order the successful exchange

Put this successful cross-origin JSON POST sequence in order.

  1. API server returns headers allowing the page origin and Content-Type.
  2. Browser sends the actual POST request.
  3. Browser checks the actual response before exposing it to Browser JavaScript.
  4. Browser sends an OPTIONS preflight request.

Apply the full distinction

Synthesize the preflight evidence

Complete all three parts from the evidence below.

  1. Write the order of these events as letters: A Browser checks the actual response before exposing it; B Browser sends OPTIONS; C API returns preflight permission for the page origin and Content-Type; D Browser sends the actual POST.
  1. State the role of each response header: Access-Control-Allow-Origin, Access-Control-Allow-Headers, and Access-Control-Allow-Methods.
  1. Classify both cases:

Case X: A JSON POST preflight returns HTTP 204 and a matching Access-Control-Allow-Origin, but it does not allow Content-Type in Access-Control-Allow-Headers. No actual POST appears.

Case Y: The JSON POST preflight allows the page origin and Content-Type; an actual POST appears, but its response lacks Access-Control-Allow-Origin.

For each case, say whether the actual request proceeded and what JavaScript can read.

Write at least 250 characters (0/250).

Step 4 of 8

Collect Evidence in Your Browser

Create a safe local GET diagnostic and capture the page origin, request details, Network evidence, Console evidence, and JavaScript outcome.

Start with observable facts

Build a reproducible record

Start with a record, not a diagnosis. For each attempt, capture these facts:

  • Page origin
  • Request URL
  • Method
  • Network evidence
  • Console evidence
  • JavaScript outcome

The Network panel and Console are separate evidence sources. A Network entry can reveal request or response details that page JavaScript cannot access. Seeing a detail in DevTools does not mean your code can read it.

Where the evidence comes from

Diagram showing Browser JavaScript sending a request through the Browser to an API server, while Network and Console panels collect evidence.

Record what the Network panel and Console show alongside what JavaScript reports.

Tip

Avoid assumptions

Use location.origin rather than guessing a localhost port. It reports the current page origin: scheme + hostname + effective port. Your Vite server may use a port other than the illustrative 5173.

Record the Console wording as you see it. Browsers can phrase the same situation differently, so an exact message is evidence—not a conclusion by itself.

Create and run a safe local GET

1. Add the local Product Catalog data

In your own Vite project, create this read-only local data file. Vite serves files in public from the site root, so this file is available at /diagnostic.json.

public/diagnostic.json

json
[{"id":1,"name":"Notebook"}]

2. Add the diagnostic page

Create diagnose.html in the project root. Start Vite, open the address it reports followed by /diagnose.html, open DevTools with both Network and Console visible, and click Run request.

This page reports to the Console only; it does not build application loading or error states. The cache: 'no-store' option makes this diagnostic GET less likely to reuse a cached response.

diagnose.html

html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Request diagnostic</title>
  </head>
  <body>
    <button id="runRequest" type="button">Run request</button>

    <script type="module">
      const runButton = document.querySelector('#runRequest');

      runButton.addEventListener('click', async () => {
        const requestUrl = new URL('/diagnostic.json', location.origin).href;
        const requestMethod = 'GET';

        console.log('Page origin:', location.origin);
        console.log('Request URL:', requestUrl);
        console.log('Method:', requestMethod);

        let response;

        try {
          response = await fetch(requestUrl, {
            method: requestMethod,
            cache: 'no-store'
          });
        } catch (error) {
          console.error('JavaScript outcome: fetch rejected', error);
          return;
        }

        console.log('JavaScript outcome:', 'Response received');
        console.log('Status:', 'HTTP ' + response.status);

        try {
          const products = await response.json();
          console.log('Products:', JSON.stringify(products));
        } catch (error) {
          console.error('JavaScript outcome: response JSON decoding failed', error);
        }
      });
    </script>
  </body>
</html>
Expected output
Page origin: http://localhost:5173
Request URL: http://localhost:5173/diagnostic.json
Method: GET
JavaScript outcome: Response received
Status: HTTP 200
Products: [{"id":1,"name":"Notebook"}]

The page origin and Request URL use the address of your own Vite server, so their port may differ. Console formatting can vary slightly by browser.

Check one key record field

Check the page-origin expression

Complete the expression that logs the current page origin.

javascript
console.log('Page origin:', );

Record evidence from your own browser

Capture your local request record

In your own diagnose.html, ensure the page-origin logging expression is complete. With Vite running, open your actual /diagnose.html address, clear Network and Console, then click Run request.

Submit one observation record from your browser. Use this structure and replace every bracketed description with what you observed:

Page origin: [actual page origin]
Request URL: [actual full request URL]
Method: [method shown]
Network evidence: [request entry and HTTP status]
Console evidence: [relevant Console lines]
JavaScript outcome: [outcome reported by the script]

Do not infer values from this tutorial's illustrative port; use your server's address.

Write at least 80 characters (0/80).

Step 5 of 8

Distinguish the Failure Categories

Use browser and JavaScript evidence together to distinguish HTTP errors, connectivity failures, mixed-content blocks, and CORS restrictions.

Recognize the evidence patterns

Start with the evidence trail

Do not diagnose a failed request from a catch block alone. Combine what JavaScript receives with what the browser records.

A readable HTTP error means fetch() resolved with a Response; code can inspect a status such as HTTP 403, even though response.ok is false.

A rejection means JavaScript received no readable Response. Connectivity trouble, mixed-content blocking, and CORS restrictions can all produce that outcome. The rejection itself does not identify which one.

Network and Console can expose facts that application JavaScript cannot read. Treat those facts as separate evidence.

Where evidence can diverge

Diagram showing Browser JavaScript, Browser, and API server, with separate paths for a readable response, a response withheld from JavaScript, a mixed-content block, and a network failure.

The browser may record more about an exchange than it exposes to Browser JavaScript.

Evidence signatures

Use these signatures as a starting point, then inspect the actual record.

A JavaScript rejection is an outcome, not a complete diagnosis.
PatternDecisive evidenceWhat it establishes
Readable HTTP errorActual request has HTTP 403; JavaScript has a ResponseThe response is readable to code.
Connectivity failureNetwork shows a failure or no HTTP status; evidence indicates a network problemNo HTTP response was made available to the browser.
Mixed-content blockHTTPS page targets an ordinary HTTP URL; Console identifies mixed contentBrowser blocked insecure active content.
CORS restrictionCross-origin record, CORS policy message, and missing or unsuitable permissionJavaScript cannot read the cross-origin result.
Hidden HTTP errorNetwork shows an actual HTTP error, but actual-response permission is absentThe server may have responded although fetch rejects.

Practice: match facts, not guesses

Match evidence to interpretation

Match each observation to the interpretation best supported by its evidence.

Tap an item and then its matching pair.

Create connectivity evidence safely

Observe a controlled offline failure

Create one controlled connectivity record with the local diagnostic page from the previous step:

  1. Keep diagnose.html open at the address reported by your Vite server.
  2. Open DevTools and select the Network panel.
  3. Set network conditions to Offline.
  4. Click Run request. The local request uses /diagnostic.json with cache: 'no-store'.
  5. Record the Page origin, Request URL, Method, Network evidence, Console evidence, and JavaScript outcome.
  6. Restore the normal network setting when finished.

Expect a failed request rather than a readable HTTP response. Console wording differs by browser, so record what you actually observe.

Warning

Avoid a false conclusion

Offline mode is evidence for this controlled test only. In an unfamiliar case, a generic fetch rejection does not prove the device is offline, does not prove CORS, and does not identify DNS or connection-refusal trouble by itself.

Integrated diagnosis

Classify complete diagnostic records

For Records A–C and for your own Offline observation, write a compact evidence-based classification using these fields:

  • Failure category
  • Decisive evidence — cite relevant Network and Console facts.
  • JavaScript outcome — readable Response or no readable Response.
  • Server receipt certainty — state only what the evidence establishes or leaves unknown.

Record A

  • Page origin: http://localhost:5173
  • Request URL: http://localhost:3000/products
  • Method: GET
  • Network evidence: Actual request shows HTTP 403. Response headers include Access-Control-Allow-Origin: http://localhost:5173.
  • Console evidence: No browser policy message.
  • JavaScript outcome: fetch() resolves to a Response with status 403.

Record B

  • Page origin: https://app.example.test
  • Request URL: http://api.example.test/products
  • Method: GET
  • Network evidence: No actual request is sent.
  • Console evidence: Browser reports mixed content.
  • JavaScript outcome: fetch() rejects.

Record C

  • Page origin: http://localhost:5173
  • Request URL: http://localhost:3000/products
  • Method: POST
  • Network evidence: OPTIONS permits the proposed request; the actual request is visible with HTTP 403. Response headers on that actual response do not include Access-Control-Allow-Origin.
  • Console evidence: Browser reports a CORS policy violation.
  • JavaScript outcome: fetch() rejects with no readable Response.

Finally, explain why an otherwise identical JavaScript outcome containing only TypeError: Failed to fetch is insufficient to diagnose CORS.

Write at least 350 characters (0/350).

Step 6 of 8

Reject Browser-Only CORS Workarounds

Reject client-side CORS bypasses and use normal browser request behavior while recognizing that readable access still depends on API-server permission.

Do not send a permission header yourself

Permission travels from the API server

CORS permission is granted by the API server in its response, not by the page making the request. Access-Control-Allow-Origin is a Response header: it tells the browser which page origin may read the response.

Putting that header into Request headers does not authorize anything. It is merely a client-authored custom header, and because it is not CORS-safelisted, it can cause the browser to send a preflight first. The API must still grant permission in its response.

Who can grant CORS permission?

Diagram showing that a client request cannot grant its own CORS permission; permission returns in response headers from the API server.

The server's response headers, not headers authored by browser JavaScript, determine whether the browser exposes a cross-origin response.

A misleading client-side change

This request does not create CORS permission.

javascript
const requestUrl = 'https://api.example.test/products';

await fetch(requestUrl, {
  headers: {
    'Access-Control-Allow-Origin': 'https://app.example.test'
  }
});

Why no-cors is not a workaround

An opaque response is not usable JSON

mode: 'no-cors' does not make restricted Product Catalog JSON available to your code. If the browser can complete an eligible cross-origin request, it gives JavaScript an opaque response.

An opaque response has an exposed status of 0, not the server's real HTTP status. JavaScript cannot read its body or response headers, so it cannot call response.json() to obtain products.

This mode also constrains methods and request headers. It is not a general substitute for a JSON API request: for example, it cannot freely use PUT, DELETE, arbitrary headers, or Content-Type: application/json. Returning to normal CORS behavior still requires the API server to grant permission.

What no-cors exposes

Diagram of an opaque response reaching the browser but being shielded from Browser JavaScript, with exposed status 0 and hidden body and headers.

Opaque means the browser does not expose the response data, headers, or real HTTP status to JavaScript.

Inspecting a no-cors response

This illustrates why the response cannot supply product data to the application.

javascript
const requestUrl = 'https://api.example.test/products';

const response = await fetch(requestUrl, {
  mode: 'no-cors'
});

console.log(response.type); // opaque
console.log(response.status); // 0
await response.json(); // Cannot read an opaque body.

Warning

Keep the browser protection in place

Do not disable browser security, install a CORS-bypass extension, or send data through an untrusted public proxy to make development appear to work. Those approaches remove or shift the protection instead of fixing the API contract, and they can expose users or data to risk. Use supported API configuration or an authorized integration path.

Reject the bypasses

Choose the safe action

A Product Catalog page at https://app.example.test cannot read a response from https://api.example.test/products because the browser reports a CORS policy failure. Which is the appropriate next action?

Use the supported request path

Complete the normal request

Complete this read request using the ordinary cross-origin configuration and the request header that communicates the representation the client can receive. The response remains readable only when the API server permits the page origin.

javascript
const requestUrl = 'https://api.example.test/products';

const response = await fetch(requestUrl, {
  mode: '',
  headers: {
    '': 'application/json'
  }
});

const products = await response.json();

Step 7 of 8

Choose the Next Action and Owner

Choose safe next actions from browser evidence and identify whether the client developer or API owner is responsible.

Assign the owner from the evidence

Start with the contract

Choose the action from the evidence—not from a browser error alone.

Client developer fixes: use the documented endpoint, use its documented HTTPS URL, and send the method and headers required by the API contract.

API owner fixes: authorize the page origin, method, and requested headers with CORS response permissions, or provide a supported integration.

Do not disguise a JSON body as another media type just to avoid a preflight. If the contract requires JSON, keep Content-Type: application/json; changing it can make the request incorrect without granting access.

Who can fix it?

A decision flow separates client-side request corrections from API-server CORS permission changes.

First align the request with the API contract. Server permission is a separate responsibility.

Evidence-to-owner guide

Use this distinction when deciding the next action.

Safe actions preserve the documented request contract.
Observed situationOwnerNext action
Request URL differs from API documentationClient developerCorrect the endpoint
HTTPS page calls an HTTP URL when HTTPS is documentedClient developerUse the documented HTTPS URL
Documented JSON request uses POST and Content-Type: application/jsonClient developerKeep the contract-aligned request
Preflight denies the required origin, method, or headerAPI ownerAuthorize the intended request
Actual response lacks Access-Control-Allow-OriginAPI ownerReturn permission on that response

Report facts without unsafe assumptions

Write a useful report

An escalation should separate observed facts from conclusions you cannot support. Use this compact conclusion structure:

Diagnosis: the evidence-based category.
Evidence: Page origin, Request URL, Method, Network evidence, Console evidence, and relevant header excerpts.
Next action: a safe, specific action.
Owner: client developer or API owner.
Server receipt certainty: what the exchange establishes—and what remains unknown.

For an API-owner report, include the OPTIONS observation and the actual-request observation when present. Label header excerpts clearly as Request headers or Response headers. Include the Console message as observed, because wording varies across browsers.

Warning

Protect data and state uncertainty

Do not include credentials, tokens, cookies, authorization values, or sensitive request payloads in a report.

A failed preflight means the browser withheld the actual request for that attempt. In contrast, an actual request whose response is unreadable to JavaScript does not prove that the server received nothing—or that a write had no effect. Verify an uncertain write through an authorized read or with the API owner; do not blindly repeat it.

Check your ownership decisions

Practice: choose the responsible owner

Match each situation to the owner and safe next action.

Tap an item and then its matching pair.

Apply the full conclusion format

Case record

Use the following Product Catalog case record. The API contract requires a JSON POST to this URL.

Page origin: https://app.example.test
Request URL: https://api.example.test/products
Method: POST with Content-Type: application/json
Network evidence: OPTIONS appears first and returns HTTP 204. Response headers: Access-Control-Allow-Origin: https://app.example.test; Access-Control-Allow-Methods: POST; Access-Control-Allow-Headers: Content-Type. An actual POST then appears with HTTP 403. Its Response headers do not contain Access-Control-Allow-Origin.
Console evidence: the browser reports that access to the POST response was blocked by CORS policy.
JavaScript outcome: fetch rejects; no readable Response is available.

Final diagnosis

Write a concise escalation for this case. Use these headings: Diagnosis, Evidence, Next action, Owner, and Server receipt certainty. Assign the safe fix to the correct owner, keep the documented JSON request intact, and state why the POST must not be blindly repeated.

Write at least 350 characters (0/350).

Step 8 of 8

Complete a Request-Failure Diagnosis

Integrate origin comparison, browser evidence, failure classification, and ownership decisions into a complete request-failure diagnosis.

Use one evidence path

Follow one evidence path

Use the same evidence path for every Product Catalog request:

  1. Compare Page origin and the request URL origin.
  2. Record the Method and inspect its Network entries.
  3. Use the Console message as supporting evidence, not the whole diagnosis.
  4. Decide whether JavaScript received a readable HTTP response, a browser restriction prevented readable access, or connectivity failed.
  5. State a safe next action, its owner, and what the evidence establishes about server receipt.

A rejected fetch() does not identify CORS by itself. In particular, distinguish a denied preflight from an actual request that was sent but whose response was withheld from Browser JavaScript.

Trace evidence before concluding

A flow diagram showing origin comparison, a possible preflight, an actual request, Network and Console evidence, and a structured conclusion.

Network and Console evidence reveal which exchange occurred and what remains uncertain.

Read three unfamiliar records

Example

Record A

Page origin: https://app.example.test

Request URL: https://api.example.test/products

Method: GET

Network evidence: An actual request is listed with HTTP 403. Response headers include Access-Control-Allow-Origin: https://app.example.test.

Console evidence: No CORS policy message appears.

JavaScript outcome: fetch() resolves to a readable Response; response.status is 403.

Example

Record B

Page origin: http://localhost:5173

Request URL: http://localhost:3000/products

Method: POST with Content-Type: application/json

Network evidence: An OPTIONS entry appears with HTTP 204, but no actual POST entry appears. Request headers include Origin: http://localhost:5173, Access-Control-Request-Method: POST, and Access-Control-Request-Headers: Content-Type. Response headers include Access-Control-Allow-Origin: http://localhost:5173 and Access-Control-Allow-Methods: POST; they do not include Access-Control-Allow-Headers permitting Content-Type.

Console evidence: The browser reports that request header Content-Type is not allowed by the preflight response.

JavaScript outcome: fetch() rejects; JavaScript receives no readable Response.

Example

Record C

Page origin: http://localhost:5173

Request URL: http://localhost:3000/products

Method: POST with Content-Type: application/json

Network evidence: OPTIONS appears first with HTTP 204. Response headers include Access-Control-Allow-Origin: http://localhost:5173, Access-Control-Allow-Methods: POST, and Access-Control-Allow-Headers: Content-Type. An actual POST then appears with HTTP 201, but its Response headers do not include Access-Control-Allow-Origin.

Console evidence: The browser reports that access to the actual response was blocked by CORS.

JavaScript outcome: fetch() rejects; JavaScript receives no readable Response.

Apply the complete diagnostic format

Produce the diagnostic conclusions

For each record—A, B, and C—write a complete conclusion using these labels:

  • Diagnosis
  • Evidence
  • Next action
  • Owner
  • Server receipt certainty

Base every claim on the supplied Network and Console evidence. In the final field, distinguish an OPTIONS request from an actual request. Do not state that a write took effect merely because the browser recorded an actual request or because JavaScript could not read its response.

Write at least 600 characters (0/600).

Review and close

Model conclusions

Compare your reasoning with these evidence-based conclusions. Browser diagnostics can show an actual exchange even when Browser JavaScript cannot access its response.

Each conclusion separates established evidence from facts that still need verification.
RecordDiagnosisEvidenceNext actionOwnerServer receipt certainty
AReadable HTTP errorActual GET is HTTP 403; allowed-origin header; readable ResponseCheck the documented access requirements and request context before changing CORS settingsClient developer firstThe API received the GET and returned HTTP 403.
BDenied preflightOPTIONS does not permit requested Content-Type; no actual POST entryRequest CORS permission for the documented Content-Type headerAPI ownerThe API received OPTIONS; the Browser withheld the actual POST for this attempt.
CActual response blocked by CORSPreflight permits POST and Content-Type; actual POST is HTTP 201 but lacks allowed-origin headerAuthorize the page origin on the actual response; verify the result through an authorized read or the API ownerAPI ownerThe actual POST reached the API and a response was recorded. The intended catalog state still needs verification.

Summary

Reusable investigation checklist

  • Start with Page origin, Request URL, and Method; do not guess the active localhost port.
  • A readable HTTP status is an application response, not a CORS failure.
  • For CORS, inspect Network entries and the Console policy message. Check whether OPTIONS and the actual request appear.
  • A failed preflight means the Browser withheld that actual request for that attempt.
  • An actual request that JavaScript cannot read may still have reached the server. Verify uncertain writes safely instead of blindly repeating them.
  • Client code can correct an endpoint, method, or documented request shape. Server CORS permission belongs to the API owner.

Tutorial complete

Congratulations! You completed: Diagnose Request Failures and CORS Restrictions

You can now diagnose browser request failures from evidence, identify the responsible owner, and communicate uncertainty about server-side effects.

Download the App now to have access to + 5000 free courses, exercises, certificates and lots of content without paying anything!

  • 100% free online courses from start to finish

    Thousands of online courses in video, ebooks and audiobooks.

  • More than 60 thousand free exercises

    To test your knowledge during online courses

  • Valid free Digital Certificate with QR Code

    Generated directly from your cell phone's photo gallery and sent to your email

Cursa app on the ebook screen, the video course screen and the course exercises screen, plus the course completion certificate