VLostBoy
VLostBoy

Reputation: 4194

Suppress Chrome 'Failed to load resource' messages in console

I'm writing a script that uses an XMLHttpRequest to search for a file defined by a relative path, by attempting to resolve that relative path against other same domain absolute paths that the script is aware of, then attempting to load the file from that resolved url. If I encounter a 404, I just try to resolve the files relative path against another absolute path, and try again. For this particular script, its perfectly fine to encounter a 404- however, my console is littered with 'Failed to load resource: the server responded with a status of 404 (Not Found) messages, and I want to suppress them.

There is no error to catch as far as I can see- error cases are handled by the xmlHttpRequest.onreadystatechange handler, and there is no window.onerror.

Is there any way to suppress these messages?

Thanks

Upvotes: 73

Views: 33917

Answers (5)

Jan Turoň
Jan Turoň

Reputation: 32912

Alas, the browsers print network error in the console if the status code is 4XX or 5XX no matter what. It is possible to filter the errors as Doug's answer suggests, but those errors are still there (i.e. they are not suppressed, just filtered) and they reappear if you uncheck the checkbox again.

To avoid those errors, the simplest solution is not to return 4XX responses from the server, but this is kind of lying and breaking the protocol like politicians do.

The clean solution on the client side can be achieved with these steps:

1. Register a service worker to intercept background requests

navigator.serviceWorker.register("noerr.js").then(_=> navigator.serviceWorker.controller
    ? window.dispatchEvent(new CustomEvent("swready")) // normal reload
    : navigator.serviceWorker.ready.then(_=> location.reload()) // first load or Ctrl+F5
);

Suppressing works since the custom swready event.

2. Replace the 4XX and 5XX responses in the service worker

The noerr.js service worker could be written like this:

self.addEventListener('install', e => {
    self.skipWaiting(); // update even if other tabs are open in the browser
});

const proxyResponse = orig => orig.status<400 ? orig : new Response(null, {
    status: 202,
    statusText: "Accepted",
    headers: new Headers({
        "Status": orig.status,
        "StatusText": orig.statusText
    })
});

self.addEventListener('fetch', e => e.respondWith(
    fetch(e.request).then(proxyResponse)
));

If the server responds 4XX or 5XX, the SW intercepts the request and returns 202 Accepted status code instead in accordance to the standard:

202 Accepted response status code indicates that the request has been accepted for processing, but the processing has not been completed; in fact, processing may not have started yet. The request might or might not eventually be acted upon, as it might be disallowed when processing actually takes place. 202 is non-committal, meaning that there is no way for the HTTP to later send an asynchronous response indicating the outcome of processing the request. It is intended for cases where another process or server handles the request, or for batch processing.

The process mentioned in the quote is our ServiceWorker which returns the original HTTP status code in the Status header.

Example

window.addEventListener("swready", _=> {
    // suppressing network errors works since now
    fetch("nonexistent.html").then(r =>
        r.headers.get("Status")==404 && console.log("Server says 404")
        // no error appears in browser console
    )
});

Now instead of console.log, the correct approach is to throw in case when the response is considered errorneous, and optionally catch it later (uncaught exceptions promote to console error).

Seamless solution

To achieve this, we can write a fetch2 function that acts like fetch(), but doesn't write console errors on 4XX and 5XX:

const fetch2 = (req, opt) => fetch(req, opt).then(res =>
    res.status!=202 ? res : new Response(null, {
        status: res.headers.get("Status"),
        statusText: res.headers.get("StatusText"),
        headers: res.headers
    })
);

// receives the response body or false if not ok
// called on any response including 4XX or 5XX
function responseHandler(body) { ... }

// called when the server does not respond
// or if the responseHandler throws
function serverError(errorEvent) { ... }

// never generates console.error
fetch2("nonexistent.html")
.then(r => r.ok && r.text())
.then(responseHandler)
.catch(serverError)

window.onerror

To clarify your question, there is window.onerror. It is not fired when the response code is 4XX or 5XX, since it is still a valid response, not error. Error is fired only if the server doesn't respond.

console.clear

console.clear() is not the right approach, since it clears all the console notes, not just network errors. In my use case, I wanted to ping the server every minute to check if it is currently available. It was daunting to debug it: to browse through thousands of console errors from the ping and look for real errors.

Upvotes: 14

Doug
Doug

Reputation: 1714

For anyone still looking for an answer to this in 2023, there's a checkbox for "hide network" under settings in the console tab.enter image description here

Upvotes: 3

Yair Levy
Yair Levy

Reputation: 1594

If you use a web worker to perform XMLHttpRequest requests, the errors will be logged into the worker script context so they will not appear on the console unless this context will be specifically chosen for display.

Upvotes: 0

Abk
Abk

Reputation: 2233

Use console.clear() in the catch block or error handler function. It will clear those request error on the console immediately after it is logged.

PLEASE NOTE

From MDN

Note that in Google Chrome, console.clear() has no effect if the user has selected "Preserve log upon navigation" in the settings.

Read more about it on MDN

try {
  var req = new XMLHttpRequest();
  req.open('GET', 'https://invalidurl', false);
  req.send();
} catch(e) {
  console.clear();
}

Should log this

GET https://invalidurl/ net::ERR_NAME_NOT_RESOLVED

but it will be cleared.

Upvotes: 11

Konrad Dzwinel
Konrad Dzwinel

Reputation: 37903

This feature was introduced last year. You can enable it here: DevTools->Settings->General->Console->Hide network messages.

Hiding network messages in Chrome DevTools

See also Filtering the Console output and Additional settings in the devtools documentation.

Upvotes: 54

Related Questions