7

We use ajax in a number of places on our website. One instance sometimes acts irregularly as if the ajax call failed. It is just in one particular location--all the others work as expected.

When the failure occurs, the user gets an error message that the operation failed.

We cannot reproduce the failure. It always just works for us. Most users do not experience the issue. The few that do sometimes report that they tried it again later and it worked.

We can simulate the failure by renaming the ajax script. Then when the operation is attempted, the ajax call fails and we get the same error message. Yet we don't have any reason to believe that the error is caused by inability to access the ajax script, although it could be. If that were the case, then the same issue should occur with our other ajax scripts.

We have come up with a workaround. If the user goes into incognito mode before attempting the operation, the problem is avoided.

The incognito mode workaround suggests that it might be related to a cookie. Accordingly, we have attempted to interfere with cookies in some way to try to recreate the problem. Nothing has succeeded.

To assist with troubleshooting, we have added additional diagnostic information to the error message, but so far nothing has come out of this other than information similar to "Error". Here is some code that shows how we are trying to get more information:

error: function (jqXHR, textStatus, errorThrown)
{
    // alert('read-unread error');
    ajaxError('Read-Unread', textStatus, errorThrown);  // TODO comment out to suppress the error reporting
},

For completeness, I have included the full javascript function below.

To set up a simple test environment to demonstrate the issue will not work very well, as it would simplify so much from the real environment as to destroy its test value. We think the only reasonable test would be to simulate a use case as the users are doing. Unfortunately that is complex, as it involves by creating a profile on our system, attempting to use the system to communicate with other members, having some response communication from the other members and then try to reply to such a communication. That re-creates the the use case, and the place where the failure occurs. Again, unfortunately, we suspect that it would still never trigger the failure for us--the toy system would also "just work".

It would be one thing it it happened to every user every time, but it does not. Only some users some of the time, and only for one ajax usage out of many on our site. Once it starts happening, at least for a while it is repeatable for that user.

My questions:

  1. How could we create a stripped down version of the environment so we could make it worthwhile for the stackoverflow community to take a look at it, short of simulating use of our website?

  2. Does the "incognito mode" workaround provide any insight to understand what is going wrong?

  3. Apart from diagnosing code that in most cases works correctly, it would be helpful to get insight on other ajax failure modes. As a made up example, such as "certain systems are too slow and the ajax times out".

[The javascript function. Note: for some reason I cannot get the first few lines of the function into the code markup.]

function toggleReadUnread(usertypeid, opp_user_label_short, principalid, repid, contactuid, value) {
    var new_response = (value) ? 'read' : 'unread';
    var prefix = '#' + contactuid;

    $('#ur-read-unread-text').html(new_response);
    $('#read-unread-dialog').dialog
    ({
        show: "fade",
        title: "Change to " + new_response + "?",
        modal: true,
        resizeable: false,
        width: getDialogWidth(400, .9),
        maxWidth: 400,
        fluid: true,
        buttons:
        {
            Ok: function ()
            {
                $(this).dialog('close');
                $.ajax(
                {
                    // async: false 
                    type: 'POST',
                    url: '/ajax/set-var.php',
                    // url: '/ajax/tr-toggle-status.php',
                    data:
                    {
                        'which_function': 'read-unread',
                        'principalid': principalid,
                        'repid': repid,
                        'usertypeid': usertypeid,
                        'value': value
                    },
                    error: function (jqXHR, textStatus, errorThrown)
                    {
                        // alert(jqXHR.responseText);
                        ajaxError('Read-Unread', textStatus, errorThrown);
                    },
                    success: function (data, textStatus, jqXHR)
                    {
                        if (data)
                        {
                            var connector = '\', \'';
                            if (value)
                            {
                                $(prefix + '-unread').remove();
                                $('<i id="' + contactuid + '-read" class="fa fa-envelope-open tooltip" onclick="toggleReadUnread(\'' + usertypeid + connector + opp_user_label_short + connector + principalid + connector + repid + connector + contactuid + '\'' + ', false);"><span id="' + contactuid + '-read-unread-tt" class="tooltiptext">You have no unread messages from this ' + opp_user_label_short + '</span>').insertAfter(prefix + '-read-unread-placeholder');
                            }
                            else
                            {
                                $(prefix + '-read').remove();
                                $('<i id="' + contactuid + '-unread" class="fa fa-envelope tooltip" onclick="toggleReadUnread(\'' + usertypeid + connector + opp_user_label_short + connector + principalid + connector + repid + connector + contactuid + '\'' + ', true);"><span id="' + contactuid + '-read-unread-tt" class="tooltiptext">You have a new message from this ' + opp_user_label_short + '</span>').insertAfter(prefix + '-read-unread-placeholder');
                                $('.tc-' + contactuid).hide();
                            }
                            jConfirm('Success', 'Messages marked "' + new_response + '"');
                        }
                    }
                })
            },
            Cancel: function () {
                $(this).dialog('close');
            }
        }
    })
 }

EDIT 1:

  1. We are still having this issue with users. We still cannot reproduce it internally.

  2. Going incognito prevents the problem from occurring. While this should be a great clue, it has not helped us so far. It seems it points to session and caching issues. We have ruled out stale cache issues.

  3. It is intermittent, and only affects a small number of users. And later even that user will no longer have the problem. Again seems like cache-related.

  4. We added diagnostic info and sometimes is says "Forbidden" in the ajax errorThrown. Checking on that implies it has to do with cross domain operations. There is no cross domain activity going on; all requests are to our own server.

  5. We have asked some users about their extensions. In one case, they had no extensions installed; in another case, they only had the Grammarly extension for Chrome. We tested with that extension and still could not reproduce the issue.

  6. When the error occurs, a dialog is displayed. After clicking "OK" on that dialog, the rest of the operation should just proceed as there is nothing that dialog blocks. However, users report they cannot complete the operation at that point when not in incognito mode.

EDIT 2:

I started looking into the https-access.log. While most accesses to the ajax file return 200, there are cases where 302 is returned. The implication is that "file is moved". But the file has not moved and shortly thereafter normal access resumes.

Here is an extract from the access log, showing a series of 200 responses, with some 302s interspersed, and then resuming 200.

108.221.39.97 - - [13/Jan/2023:10:07:52 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
108.221.39.97 - - [13/Jan/2023:10:08:34 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
108.221.39.97 - - [13/Jan/2023:10:09:56 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
73.176.158.231 - - [13/Jan/2023:10:10:21 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
74.73.226.238 - - [13/Jan/2023:10:15:07 -0600] "POST /ajax/set-var.php HTTP/2.0" 302 - "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
184.178.239.162 - - [13/Jan/2023:10:15:18 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?reply=tr-28560-80354" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.76"
74.73.226.238 - - [13/Jan/2023:10:15:20 -0600] "POST /ajax/set-var.php HTTP/2.0" 302 - "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
24.144.188.195 - - [13/Jan/2023:10:15:22 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
74.73.226.238 - - [13/Jan/2023:10:15:28 -0600] "POST /ajax/set-var.php HTTP/2.0" 302 - "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
74.73.226.238 - - [13/Jan/2023:10:15:34 -0600] "POST /ajax/set-var.php HTTP/2.0" 302 - "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
74.73.226.238 - - [13/Jan/2023:10:15:37 -0600] "POST /ajax/set-var.php HTTP/2.0" 302 - "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
74.73.226.238 - - [13/Jan/2023:10:15:49 -0600] "POST /ajax/set-var.php HTTP/2.0" 302 - "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
72.38.12.208 - - [13/Jan/2023:10:15:54 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?reply=tr-43850-7444" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.76"
74.73.226.238 - - [13/Jan/2023:10:16:07 -0600] "POST /ajax/set-var.php HTTP/2.0" 302 - "https://www.rephunter.net/track-relationships.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
74.73.226.238 - - [13/Jan/2023:10:16:19 -0600] "POST /ajax/set-var.php HTTP/2.0" 302 - "https://www.rephunter.net/track-relationships.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
108.221.39.97 - - [13/Jan/2023:10:17:23 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
108.221.39.97 - - [13/Jan/2023:10:17:28 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
72.38.12.208 - - [13/Jan/2023:10:17:49 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?reply=tr-43850-7444" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.76"
108.221.39.97 - - [13/Jan/2023:10:17:58 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
24.45.242.118 - - [13/Jan/2023:10:20:41 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
24.45.242.118 - - [13/Jan/2023:10:21:10 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"

EDIT 3:

We have a candidate solution inspired by the comment from @ibrahim to the answer from Lajos Arpad below. In short, adding retry functionality to the ajax call as shown at https://forum.framework7.io/t/app-request-what-is-the-best-way-to-retry-an-ajax-request-using-app-request/4759, which appears to be based on What's the best way to retry an AJAX request on failure using jQuery?.

After we confirm that this fix works, which will take some time of "no reported errors", I would mark it as the "answer", should @ibramim post his comment about retries as an answer.

Jeffrey Simon
  • 918
  • 3
  • 11
  • 25
  • All these problems sound like stale cache issues. Ie the problems occur when users have old cached copies of your `.js` files. Use [cache-busting techniques](https://tomanistor.com/blog/cache-bust-that-asset/) like content fingerprinting and appropriate cache headers on your HTML resources. – Phil Dec 06 '22 at 23:40
  • Where (which part/variables) does your ajax use cookies ? (if there are none, then it cannot be related to cookies, right ? ) – Ken Lee Dec 06 '22 at 23:42
  • 1
    Is there a missing comma between `contactuid value` in toggleReadUnread function parameters ? – Ken Lee Dec 06 '22 at 23:46
  • @Phil - we already use a cache-busting technique, where each file update results in a random number included in the filename, and URL rewriting to get the real file. However, if it was a cache issue, the normal "clear cache" would seem to fix it. I believe one of our first attempts with the users was to have them clear cache. – Jeffrey Simon Dec 08 '22 at 00:15
  • @JeffreySimon that all sounded good until _"URL rewriting"_. The requests for your files should be for the unique filename. Eg your HTML should have ` – Phil Dec 08 '22 at 00:18
  • @Ken Lee--you bring up an interesting point, which bears further examination. Our ajax scripts do use the existing session for the user. Normally this works fine. But maybe there is something in this case. However, the problem seems to not be that the ajax script cannot find the session, but rather that the browser/server connection cannot even find the ajax script. – Jeffrey Simon Dec 08 '22 at 00:20
  • @Phil -- I think our implementation is what you suggest. For example, I just loaded the page, and in dev tools source see that the tag is as follows: . It is the URL rewriting that serves library-1.js. HOWEVER, in looking at the html, I am wondering is the async can be causing file unavailable issues. In fact that is such a strong hint, I believe it is worth removing it to see if that improves things. Do you agree? – Jeffrey Simon Dec 08 '22 at 00:27
  • @Ken Lee - very sharp eye! In fact there is a missing comma in the uploaded code snippet. As I mentioned, I had a lot of trouble getting that snippet to post, as SO kept putting part of the text outside the code markup. In any case, the comma is not missing in the original source code (that would cause problems!). I have edited the question to put the comma back in. – Jeffrey Simon Dec 08 '22 at 00:30
  • @JeffreySimon use code-fences. See https://stackoverflow.com/help/formatting – Phil Dec 08 '22 at 00:31
  • @Phil - thanks for the link to the formatting page. – Jeffrey Simon Dec 08 '22 at 00:36
  • Hi Jeff, normally it is not quite likely that the browser cannot "find" the ajax part to execute because the code is on the user computer (client-side), but since you mentioned sessions (I believe some of the ajax variables values are from sessions ?), then please be reminded that the default PHP session timeout is 24 minutes. (if the session expires, it/they will disappear and cause error(s) ) FYI, you may edit php. ini to change the timeout value – Ken Lee Dec 08 '22 at 01:16
  • @Ken Lee--we use a custom session handler and the normal timeout is 60 minutes. However, it does not seem to be an issue with timeouts. You can have people start a brand new session and the issue still occurs. – Jeffrey Simon Dec 08 '22 at 19:45
  • I just worked over the phone with a user having the problem today. That means that removing the html async attribute from the link to the script did not solve the problem. However, the user reported that the additional error information that was provided in errorThrown is "Forbidden". This seems that it could be a 403 error on the ajax script. However, please note that (1) this issue only affects a small percentage of users; (2) going into incognito mode works around the issue, enabling those users to get their work done. – Jeffrey Simon Dec 08 '22 at 19:49
  • Try adding `` to the top of all concerned PHP/HTML scripts and see what happens (reason: disable cache on these scripts) – Ken Lee Jan 15 '23 at 04:01
  • Is your site available on HTTP or purely HTTPS? As in, is there any way that the page the user is on is requesting the HTTP version of the site (so `/ajax/set-var.php` resolves to `http://yoursite.com/ajax/set-var.php`) and the 302 is redirecting to the HTTPS version of the page? – Luke Jan 16 '23 at 11:02
  • @Ken Lee-the cache disabling looks very interesting. However, it would have to be handled a bit differently due to our template system. – Jeffrey Simon Jan 20 '23 at 21:28
  • @Ken Lee. Our main pages already send the Cache-Control: no-store, no-cache, must-revalidate. But have to check on the ajax call. – Jeffrey Simon Jan 20 '23 at 21:36
  • @Ken Lee. The page at https://api.jquery.com/jquery.ajax/ says there is a cache attribute that can be set to false, but that it only works for HEAD and GET requests. Our request is a POST. Not sure where to go with this. – Jeffrey Simon Jan 20 '23 at 21:42
  • Is there any redirect coded in `set-var.php`? – Olivier Jan 21 '23 at 09:29

2 Answers2

5

Symptom

You have an issue with an AJAX script that generally works, but for some (rare) users sometimes the file is briefly not found.

Work-around

Using incognito mode seems to work this around.

Are we sure about the work-around?

There is some slight chance that the work-around coincides but does not cause the resuming of the AJAX. It is possible therefore that very rarely the file is unavailable (ex. there is an intermittent script rebuilding/minimizer that temporarily removes the file in order to move the new version in its place) for a very brief amount of time and users are experiencing the problem you have mentioned, yet, by the time they try to reach it via incognito mode, the file is already restored, in short: it is possible that the incognito mode is only coinciding with the restoration of the file, but not causing this.

Disproving this could be tried by trying out the incognito work-around when the issue happens, see that it works and then try in non-incognito mode and see it still not working (after a page reload, of course). In the latter part of the answer I will presume that incognito is causing the issue to disappear for the user and not only coincides with the disappearance of the problem.

Possible causes

Cookies

Some cookies are problematic. For example, the cookie of the user expired and cannot validly be used, yet, the page has started to load when the cookie was still valid, yet, the server throws a file moved error for the request to the file because it is programmed to serve this request only for logged in users. Also, it's possible that /ajax/set-var.php on its own tries to load some file that surely exists for existent session, but the current session has been destroyed and the file to be reached no longer exists.

Cache

Client-side caches may have an exact filename or path whereas the file has been renamed or moved. It is also possible that the file was requested during a build process, when the file was being written and that incomplete file has been cached into the browser. In your case this does not seem to be the problem, since you have a php file that's being moved according to the error message.

Server-side may have cached some information for you that has become deprecated/invalid since then. For instance, a static page generated for the user's session to avoid repeating the same long request logic.

sessionStorage / localStorage

It's quite possible that some values are stored in sessionStorage and are lost when the session times out, yet the page is still loaded, or some values specific to a session are stored in localStorage and no longer valid. In both cases the request is invalid and on the server-side there is some error being thrown, resulting file not found.

What could file not found mean?

It means that some file is not found at the expected location. So, in order to fix it:

  • check the error logs as well around the time when the error happens and see whether some exception/error/notice is being stored
  • study all jobs that are writing critically important files, like cron jobs, build processes, minifiers, etc.
  • study /ajax/set-var.php, particularly the section that handles this request
  • study carefully https://www.rephunter.net/track-relationships.php
Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175
  • Very detailed and thoughtful response. Regarding the incongnito mode being the the direct solution: while we don't understand why incognito mode is the solution other than it in effect clears the session, the suggestion that the it allows the file to be restored after time elapses. While I cannot comment on that due to observation, we do see something that I did not point out in the original question that the user can repeatedly attempt the action and get repeated failures, and if it were a temporary unavailability it would see that just such retries would also solve the problem. More to come. – Jeffrey Simon Jan 20 '23 at 20:06
  • Regarding cache and cookies, it does seem these are related. The odd thing is that set-var.php is a multipurpose script, and it is called from several places. But only this one place has the problem. Because of uncertainties here and as a straw to reach for, we have created a dedicated Ajax script that only has the one function in question. The idea being that maybe the file is busy, and having a separate, dedicated file might allow it to be less busy. Since we factored out that one function on 14-Jan-23, six days ago, we have not had this problem reported. Not enough time to be sure yet. – Jeffrey Simon Jan 20 '23 at 20:38
  • The session storage issue is also countered by the repeated errors upon retry for the users in this condition. However a related clue is that normally each user who has the problem reports that the following day "it works fine again". So it does point so some kind of session-related thing. – Jeffrey Simon Jan 20 '23 at 20:40
  • The error logs do shed light, as stated in the EDITs. That is, there is a string of 200 result codes, and the unexpected 302 codes for a user. – Jeffrey Simon Jan 20 '23 at 20:43
  • *"sometimes the file is briefly not found"* The status code is 302, not 404. – Olivier Jan 21 '23 at 09:26
  • @JeffreySimon From the information you have shared it seems that maybe set-var.php is using some resource that's related to user sessions and that resource gets temporarily missing. Is the new clone feature you have implemented having the same source-code as the one that was running for this request previously? – Lajos Arpad Jan 21 '23 at 11:44
0

There could be a ton of things going wrong in backend, so with that in mind, my first approach would be to simulate 'fresh request', like in cognito as much as possible:

1- Make a function to generate a random hexstring, you will use this to append it as a query string to your request so it cannot be cached:

function genHex(n){
    return Array.from({length:n}).reduce((ac,d) => ac += (Math.random() * 1e6 | 0).toString(16),"")
}

genHex(2)//'7ec05646dc'

2- Add the request headers to invalidate cache:

            $.ajax({
                    asynch: false,//what the hell is this 'asynch'??
                    type: 'POST',
                    url: '/ajax/set-var.php?' + genHex(2),
                    headers:{
                      "Cache-control": "no-cache, no-store, must-revalidate",
                      "Pragma": "no-cache",
                      "Expires": "0"
                    },

The idea is that, if your server disregards the cache control headers for whatever reason, at least we have the random query parameter to simulate similar behavior. Try it out and let me know, otherwise I will delete.

3- Wrap everything in a function that self executes itself on error with a set limit.

function reAjax(limit = 2, firstCall = true, ...rest){
    if(!limit){return}
    $.ajax({
        asynch: false,//what the hell is this 'asynch'??
        type: 'POST',
        url: `/ajax/set-var.php${firstCall ? "" : `?${genHex(2)}`}`,
        headers:{
          "Cache-control": "no-cache, no-store, must-revalidate",
          "Pragma": "no-cache",
          "Expires": "0"
        },
        error: (...rest) => reAjax(--limit, false, ...rest)  
    })
}

The function will call itself without query parameters (for cache busting) the first time and it will keep calling on error with cache busting until limit is hit. rest is the parameters passed on jquery error here

PS: One more thing to add, if your backend is controlled by a third party virtual machine, sometimes they put rate-limiting on how many POST requests one can make. Essentially they act as a reverse proxy between you and the client. So make sure these limitations are NOT the case

ibrahim tanyalcin
  • 5,643
  • 3
  • 16
  • 22
  • We control our server and there is no rate limiting. – Jeffrey Simon Jan 20 '23 at 21:15
  • After writing the question we found the invalid asynch and removed it. We did not change it to async, because it occurred to us that async: false could be part of the problem. After removing it, the issue did continue anyways. – Jeffrey Simon Jan 20 '23 at 21:17
  • The random query string looks like an interesting approach. We use a similar auto-versioning to force reloading of all css and js files when they are modified. I don't understand however what to look for. Is doing that supposed to prevent the issue from occurring, or is it supposed to have some other observable result? – Jeffrey Simon Jan 20 '23 at 21:23
  • Because you mentioned on re-visiting the issue is fixed. So first thing to try is to force disable cache and see if that works. However 302 suggests many other things, like file being moved by server-side briefly to one location,then to another. It could also be a session variable or auth token expired right before. So if you are sure that re-visitng/re-requesting the same URL fixes the problem, why not retry Fetch/XMLHTTPrequest 1 more time if non-2XX status is returned? That way, the right cookies will be set on 1st faulty request, and 2nd will work as desired – ibrahim tanyalcin Jan 21 '23 at 09:54
  • Revisiting was not effective, but using browser incognito mode always worked around the problem, and once that workaround happened, the problem no longer occurred, pointing to a cookies/session issue. HOWEVER, you finaly point about retry led me to search and let to the page at https://forum.framework7.io/t/app-request-what-is-the-best-way-to-retry-an-ajax-request-using-app-request/4759, and then to the page at https://stackoverflow.com/questions/10024469/whats-the-best-way-to-retry-an-ajax-request-on-failure-using-jquery. I implemented the retry mechanism as shown on these two pages. – Jeffrey Simon Mar 28 '23 at 19:02
  • Continuing--I implemented a retry mechanism, and while rolling it out into production, a user called us with the problem. I worked with the user, and it might be a solution, because after making sure he had the new code, the problem no longer occurred, whereas previously once the problem occurred the only way out of it was via incognito mode. That is, browser restarts and cache clearing were insufficient to correct it. BOTTOM LINE: you should post an answer with the "retry" suggestion, and I may be able to award points, if it turns out the full problem is fixed. – Jeffrey Simon Mar 28 '23 at 19:04
  • Morning Jeffrey, I will do that in the afternoon, thanks for letting me know. – ibrahim tanyalcin Mar 29 '23 at 06:29