Closed Bug 2027860 Opened 15 days ago Closed 4 days ago

Firefox experiences some noticeable delay before showing file-not-found page content, due to setTimeout in retryErrorCode

Categories

(Firefox :: Security, defect, P2)

defect

Tracking

()

RESOLVED FIXED
151 Branch
Tracking Status
firefox-esr140 --- unaffected
firefox149 --- wontfix
firefox150 --- wontfix
firefox151 --- fixed

People

(Reporter: dholbert, Assigned: jbrown)

References

(Blocks 1 open bug, Regression)

Details

(Keywords: perf, regression)

Attachments

(2 files)

STR:

  1. Visit file:// URI for a filename that does not exist, e.g. file:///tmp/bogus-file.html
  2. (optional) Reload the page.

ACTUAL RESULTS:
There's a notable delay (feels like 1/2 second or so) where the content area is just blank, before the actual "File not found" UI shows up.

EXPECTED RESULTS:
No such delay.

Regression range:
https://hg.mozilla.org/integration/autoland/pushloghtml?fromchange=ffeda2cc60998e963e7d0cbbaf025926680129f0&tochange=9f7ec0c93a48daec7f488903dd24d2a9e4fea4f3

--> Regression from bug 2003587.

Set release status flags based on info from the regressing bug 2003587

:jbrown, since you are the author of the regressor, bug 2003587, could you take a look? Also, could you set the severity field?

For more information, please visit BugBot documentation.

Here's a profile taken in the first-bad Nightly (2026-01-01), where I'm just reloading a bogus file:// URL several times:
https://share.firefox.dev/3NVxFwT

As shown in the profile:

  • The page is blank for ~380ms during each reload operation.
  • and we're idle for most of that time, so it's not clear if anything useful is happening?

Looking a bit closer, there's a somewhat-long setTimeout involved -- the file:// content-process shows "setTimeout callback" about 100ms into the idle period. That looks to be for this function:

https://searchfox.org/firefox-main/rev/0ea834f7eeb962c70f3232e782830290e63c0951/toolkit/content/aboutNetError.mjs#1316-1320

async function retryErrorCode() {
  return new Promise(res => {
    setTimeout(() => {
      res(getErrorCode());
    }, 100);

...which was indeed added in the regressor commit, here:
https://hg-edge.mozilla.org/integration/autoland/rev/9f7ec0c93a48daec7f488903dd24d2a9e4fea4f3#l19.29

I suspect that 100ms delay is responsible for most-if-not-all of the issue here.

Jack, could you take a look? Is there a reason we've got that 100ms delay there, and is it expected to be something that gets exercised for simple scenarios like loading a file-not-found page?

(as a shot in the dark... maybe there's no network error-code associated with this file-not-found page, and so that's needlessly making us hit this retryErrorCode fallback code-path?)

Yup, that's exactly it. Using regular devtools (no browser toolbox needed), I was able to step through this in the DevTools debugger.

  1. In chrome://global/content/aboutNetError.mjs , we hit init() which calls getErrorCode() like so:
    https://searchfox.org/firefox-main/rev/0ea834f7eeb962c70f3232e782830290e63c0951/toolkit/content/aboutNetError.mjs#1324-1330
async function init() {
  let errorCode = await getErrorCode();
  let i = 0;
  while (!errorCode && i < 3) {
    i++;
    errorCode = await retryErrorCode();
  }
  1. Inside getErrorCode(), we see that gIsCertError is false so we return document.getNetErrorInfo().errorCodeString -- which for this page is an empty string (i.e. "")

  2. So: back up in init, our !errorCode truthiness-check fails (the empty string evaluates to false), and we call retryErrorCode(), which is doomed to get the same empty-string response (I assume) three times in a row. So we eat up 300ms (3 loops with a 100ms setTimeout in each) for no good reason, before we get around to painting the page.

No longer blocks: 2003587

Note for testing & regression-tracking purposes: the regressor here happened to include a pref-flip (toggling security.certerrors.felt-privacy-v1 to true), but this bug reproduces regardless of whether that about:config pref is true or false. This bug was introduced by other logic that was in the regressing commit, and that logic runs regardless of the pref's true/false value.

So: this was a new regression in 148 and affects all releases since then, independent from pref values (and I confirmed that it affects current release v149 with a fresh Firefox profile).

Summary: Firefox experiences some noticeable delay before showing file-not-found page content → Firefox experiences some noticeable delay before showing file-not-found page content, due to setTimeout in retryErrorCode
See Also: → 2028136
Assignee: nobody → jbrown
Status: NEW → ASSIGNED

Hey Daniel, I remember I had to add the retry logic in D275665 because we need to give IPC enough time to deliver the cert security info for subframe cert errors. I mentioned this in a comment in that patch:

When a subframe hits a cert error, the error page would load and run NetErrorCard.isSupported() immediately, and sometimes the parent process hadn't finished sending the failed-channel security info yet via IPC by that time.

Then we'd end up with an undefined errorCodeString, isSupported would return false, and the legacy page would render instead of net-error-card.

On the other hand, we only need this for cert errors, and the file:// not-found pages you mentioned are not cert errors.

We should be able to gate the retry loop on gIsCertError. I added a patch with this change.

Flags: needinfo?(jbrown)
Blocks: 1990918
Severity: -- → S3
Keywords: perf
Priority: -- → P2
Status: ASSIGNED → RESOLVED
Closed: 4 days ago
Resolution: --- → FIXED
Target Milestone: --- → 151 Branch

The patch landed in nightly and beta is affected.
:jbrown, is this bug important enough to require an uplift?

For more information, please visit BugBot documentation.

Flags: needinfo?(jbrown)
Flags: needinfo?(jbrown)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: