Parse-sdk-js: "_synchronizeAllAuthData is not a function" when running in production after 2.9.0 update

Created on 11 Nov 2019  Â·  23Comments  Â·  Source: parse-community/Parse-SDK-JS

Issue Description

After updating to Parse 2.9.0, we started noticing a new error when running Parse.User.current(), but only when running in production. Downgrading to 2.8.0 fixes the issue. The error thrown is:

TypeError: n._synchronizeAllAuthData is not a function
  at Object.currentUser (ParseUser.js:1266)

Steps to reproduce

  1. Run a web app using the Parse SDK v2.9.0 in production (NODE_ENV=production)
  2. Successfully authenticate as user using Parse.User.logIn method
  3. Reload the web page and trigger Parse.User.current()

Expected Results

Should return a Parse.User object with the current user.

Actual Outcome

Throws error: "_synchronizeAllAuthData is not a function"

Environment Setup

  • Server

    • parse-server version (Be specific! Don't say 'latest'.) : 3.9.0
    • Operating System: Mac OS 10.14.5
    • Hardware: MacBook Pro 2019
    • Localhost or remote server? (AWS, Heroku, Azure, Digital Ocean, etc): Localhost
  • JS SDK

    • JS SDK version: 2.9.0
    • Application? (Browser, Node, React-Native, etc): VueJS App

Logs/Trace

ParseUser.js:1266 Uncaught (in promise) TypeError: n._synchronizeAllAuthData is not a function
    at Object.currentUser (ParseUser.js:1266)
    at Function.value (ParseUser.js:781)
    at actions.ts:81
    at l (runtime.js:45)
    at Generator._invoke (runtime.js:271)
    at Generator.M.forEach.e.<computed> [as next] (runtime.js:97)
    at qe (app.c0811891.js:1)
    at a (app.c0811891.js:1)
    at app.c0811891.js:1
    at new Promise (<anonymous>)
needs investigation

Most helpful comment

@RaschidJFR did you try clearing your cache / refresh the browser?

All 23 comments

I had this issue today, it only occurred once i deployed the code to a docker container, running locally on the React webpack dev it didn't happen.

Specs of the failed system were

Parse-server 2.9.0
Express 4.17.1
node v12.13.0
Alpine Linux
React 16.11.0

Error thrown was
"_synchronizeAllAuthData is not a function"

With a fresh browser you could call the login and make queries, on refresh it would throw the error until you clear the localStorage.

So we also only saw it after we actually deployed the code but, after further investigation, we found that it was related to the NODE_ENV variable which, when serving the app locally, defaults to "development". I only can confirm this with Vue but I'd be curious if you get the same error locally if you set your mode to production when running it locally.

On Nov 11, 2019, at 1:02 PM, jamesmogg notifications@github.com wrote:


I had this issue today, it only occurred once i deployed the code to a docker container, running locally on the React webpack dev it didn't happen.

Specs of the failed system were

Parse-server 2.9.0
Express 4.17.1
node v12.13.0
Alpine Linux
React 16.11.0

Error thrown was
"_synchronizeAllAuthData is not a function"

With a fresh browser you could call the login and make queries, on refresh it would throw the error until you clear the localStorage.

—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or unsubscribe.

Getting the same error in production:

TypeError: t._synchronizeAuthData is not a function at

Uncaught (in promise) Error: XMLHttpRequest failed: {}

I am getting something similar, not sure if related. This happens in a production build of an iOS app, regardless if deployed on device or simulator.

XMLHttpRequest failed: {"line":519,"column":4087,"sourceURL": "/Users/sam/Library/Developer/ CoreSimulator/Devices/ IE6DBED1-8CAD-4A6E-84FF- E352C4DBA528/data/Containers/ Bundle/Application/ B359A263-9AC8-4021-8E23-106D92 C20143/AusTVStaging.app/ main.jsbundle"}

image

I extracted line 519 from the bundle, on column 4087 (marked below with "<---") is the following method:

request: function(t, n, u, l) {
        l = l || {};
        var p = s.default.get("SERVER_URL");
        "/" !== p[p.length - 1] && (p += "/"), (p += n);
        var c = {};
        if (u && "object" == typeof u) for (var E in u) c[E] = u[E];
        "POST" !== t && ((c._method = t), (t = "POST")),
          (c._ApplicationId = s.default.get("APPLICATION_ID"));
        var T = s.default.get("JAVASCRIPT_KEY");
        T && (c._JavaScriptKey = T),
          (c._ClientVersion = s.default.get("VERSION"));
        var y = l.useMasterKey;
        if ((void 0 === y && (y = s.default.get("USE_MASTER_KEY")), y)) {
          if (!s.default.get("MASTER_KEY"))
            throw new Error(
              "Cannot use the Master Key, it has not been provided."
            );
          delete c._JavaScriptKey, (c._MasterKey = s.default.get("MASTER_KEY"));
        }
        s.default.get("FORCE_REVOCABLE_SESSION") && (c._RevocableSession = "1");
        var S,
          O = l.installationId;
        O && "string" == typeof O
          ? (S = Promise.resolve(O))
          : (S = s.default.getInstallationController().currentInstallationId());
        return S.then(function(t) {
          c._InstallationId = t;
          var n = s.default.getUserController();
          return l && "string" == typeof l.sessionToken
            ? Promise.resolve(l.sessionToken)
            : n
            ? n.currentUserAsync().then(function(t) {
                return t
                  ? Promise.resolve(t.getSessionToken()) <---- here
                  : Promise.resolve(null);
              })
            : Promise.resolve(null);
        })
          .then(function(n) {
            n && (c._SessionToken = n);
            var s = JSON.stringify(c);
            return v.ajax(t, p, s, {}, l).then(function(t) {
              var n = t.response,
                s = t.status;
              return l.returnStatus ? f({}, n, { _status: s }) : n;
            });
          })
          .catch(function(t) {
            var n;
            if (t && t.responseText)
              try {
                var s = JSON.parse(t.responseText);
                n = new o.default(s.code, s.error);
              } catch (s) {
                n = new o.default(
                  o.default.INVALID_JSON,
                  "Received an error with invalid JSON from Parse: " +
                    t.responseText
                );
              }
            else
              n = new o.default(
                o.default.CONNECTION_FAILED,
                "XMLHttpRequest failed: " + JSON.stringify(t)
              );
            return Promise.reject(n);
          });
      }

I downgraded to 2.8.0 and issue is now gone.

Hey guys the issue is caused by https://github.com/parse-community/Parse-SDK-JS/pull/978

Looks like this doesn't like minified code (ParseUser doesn't exist as it has been minified to a variable like 'e'). We could revert this or someone can try a PR.

I opened a PR https://github.com/parse-community/Parse-SDK-JS/pull/999.

Can you see if it works for you?

Can confirm, PR #999 fixed the issue we were seeing.

I've updated to 2.9.1 but the problem persists. So I rolled back to 2.8.0, the problem is fixed for me.

@RaschidJFR did you try clearing your cache / refresh the browser?

Same problem even in different browser and incognito mode

@RaschidJFR Are you receiving the same errors as above? Also are you using a Parse.User subclass?

I was indeed using a subclass in my Ionic app, but even without it the error persists.

This simple block:

Parse.initialize(environment.parse.appId, environment.parse.javaScriptKey);
(Parse as any).serverURL = environment.parse.serverUrl;
Parse.User.current();

throws this errors:

custom-error-handler.service.ts:37 TypeError: current._synchronizeAllAuthData is not a function
    at Object.currentUser (ParseUser.js:1264)
    at Function.value (ParseUser.js:781)
    at AppComponent.initParse (app.component.ts:37)
    at AppComponent.initializeApp (app.component.ts:30)
    at new AppComponent (app.component.ts:19)
    at createClass (core.js:27869)
    at createDirectiveInstance (core.js:27685)
    at createViewNodes (core.js:38315)
    at createRootView (core.js:38187)
    at callWithDebugContext (core.js:39716)

Can you debug the currentUser function? I do have an ionic app. I’ll try to replicate this.

Same here. I upgraded to 2.9.1, and now even after going back to 2.8.0 the issue remains.

I am using a subclass for Parse.User.

The error is thrown here, ParseUser.js, line 1203:

    var current = _ParseObject2.default.fromJSON(userData);
    // After this call, current doesn't have the _synchronizeAllAuthData function

    currentUserCache = current;

    // and so it crashes here:
    current._synchronizeAllAuthData();

    return current;

FYI, I found a fix for my specific issue. I was subclassing Parse.User with my own User class, and then I was calling:

Parse.Object.registerSubclass('_User', User);

At boot up, User.current() is called, the stored class name is User, not _User. And so Parse cannot find the constructor and returns a regular Parse.Object instead, which lacks the _synchronizeAllAuthData function.

tl;dr:
I changed the registerSubClass function to:

Parse.Object.registerSubclass('User', User); // no underscore
Parse.Object.registerSubclass('_User', User); // left this one too, just in case

Hope this helps anyone out there with this issue.

@josenriq thanks for reporting a fix. I can do a PR that will register to both User and _User.

@josenriq This was brought up. https://github.com/parse-community/docs/pull/680#issuecomment-549504835

Im against overriding the _User subclass, but it seems like a lot of developers are doing it.

@RaschidJFR Quick question how are you subclassing your Parse.User and registering it? Is it 'User' or '_User'?

Can you see if the fix above works for you?

I always use _User. And yes, to me it’s really handy to create my own customized User subclasses with the functions and props my apps need. I usually work on Angular (typescript).

@josenriq thanks for having a look at the issue. I’ll try your solution.

I'm afraid this issue keeps happening for subclassed Parse.User classes and minified code.

For example, in an Angular project, unless you eject the configuration or install a custom builder to intercept Terser and keep class names, the following code breaks:

https://github.com/parse-community/Parse-SDK-JS/blob/master/src/ParseUser.js#L874

    json.className = user.constructor.name === ParseUser.name ? '_User' : user.constructor.name;

because user.constructor.name is not the same name that was passed via Parse.Object.registerSubclass. Instead, it is an arbitrary string produced by minification. And thus, when ParseUser.current() is called, the minified className is not found, and a regular Parse object is returned instead a User instance.

@dplewis what do you think about

json.className = user.className === ParseUser.name ? '_User' : user.className;

instead of

json.className = '_User'

I confirm that from 2.10.0 is working again. Thanks @dplewis

"parse": "^2.13.0",
"@types/parse": "^2.12.1",
Not working

Was this page helpful?
0 / 5 - 0 ratings

Related issues

anhhtz picture anhhtz  Â·  3Comments

ryanemax picture ryanemax  Â·  7Comments

marktyers picture marktyers  Â·  3Comments

dplewis picture dplewis  Â·  7Comments

futureinapps picture futureinapps  Â·  3Comments