Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v9.0.2 auth] INTERNAL ASSERTION FAILED: Expected a class definition #5475

Closed
bramvanneerven opened this issue Sep 10, 2021 · 14 comments · Fixed by #5527
Closed

[v9.0.2 auth] INTERNAL ASSERTION FAILED: Expected a class definition #5475

bramvanneerven opened this issue Sep 10, 2021 · 14 comments · Fixed by #5527

Comments

@bramvanneerven
Copy link

In an effort to reduce the dependencies of the authentication code I use, I tried the following:

// Works
import { getAuth } from 'firebase/auth';
const auth = getAuth(app);

// ERROR!
import { browserLocalPersistence, initializeAuth } from 'firebase/auth';
const auth = initializeAuth(app, { persistence: browserLocalPersistence });
Error output
Error: INTERNAL ASSERTION FAILED: Expected a class definition
    at debugFail ({***path***}/node_modules/.pnpm/@firebase+auth@0.17.2_@firebase+app@0.7.0/node_modules/@firebase/auth/dist/node/index-012195c6.js:535:11)
    at debugAssert ({***path***}/node_modules/.pnpm/@firebase+auth@0.17.2_@firebase+app@0.7.0/node_modules/@firebase/auth/dist/node/index-012195c6.js:546:9)
    at _getInstance ({***path***}/node_modules/.pnpm/@firebase+auth@0.17.2_@firebase+app@0.7.0/node_modules/@firebase/auth/dist/node/index-012195c6.js:568:5)
    at Array.map (<anonymous>)
    at _initializeAuthInstance ({***path***}/node_modules/.pnpm/@firebase+auth@0.17.2_@firebase+app@0.7.0/node_modules/@firebase/auth/dist/node/index-012195c6.js:637:80)
    at {***path***}/node_modules/.pnpm/@firebase+auth@0.17.2_@firebase+app@0.7.0/node_modules/@firebase/auth/dist/node/index-012195c6.js:6979:13
    at Component.instanceFactory ({***path***}/node_modules/.pnpm/@firebase+auth@0.17.2_@firebase+app@0.7.0/node_modules/@firebase/auth/dist/node/index-012195c6.js:6981:11)
    at Provider.getOrInitializeService ({***path***}/node_modules/.pnpm/@firebase+component@0.5.6/node_modules/@firebase/component/dist/index.cjs.js:342:39)
    at Provider.initialize ({***path***}/node_modules/.pnpm/@firebase+component@0.5.6/node_modules/@firebase/component/dist/index.cjs.js:264:29)
    at initializeAuth ({***path***}/node_modules/.pnpm/@firebase+auth@0.17.2_@firebase+app@0.7.0/node_modules/@firebase/auth/dist/node/index-012195c6.js:632:25)
package.json
  "dependencies": {
    "@chakra-ui/react": "^1.6.7",
    "@chakra-ui/theme-tools": "^1.2.0",
    "@emotion/react": "^11.4.1",
    "@emotion/styled": "^11.3.0",
    "@xstate/react": "^1.6.1",
    "common-tags": "^1.8.0",
    "firebase": "^9.0.2",
    "framer-motion": "^4.1.17",
    "next": "11.1.0",
    "react": "17.0.2",
    "react-dom": "17.0.2",
    "react-icons": "^4.2.0",
    "sharp": "^0.29.1",
    "xstate": "^4.23.4"
  },
  "devDependencies": {
    "@types/common-tags": "^1.8.1",
    "@types/react": "17.0.18",
    "eslint": "7.32.0",
    "eslint-config-next": "11.1.0",
    "eslint-plugin-import": "^2.24.2",
    "lint-staged": "^11.1.2",
    "prettier": "^2.4.0",
    "simple-git-hooks": "^2.6.1",
    "typescript": "4.3.5"
  },

The problem seems to be here:

debugAssert(cls instanceof Function, 'Expected a class definition');

I did have a quick look, but could not really find the actual problem myself.

@google-oss-bot
Copy link
Contributor

I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.

@arneesh
Copy link

arneesh commented Sep 10, 2021

I am experiencing the same issue.

@jbalidiong
Copy link
Contributor

Hi @bvanneerven, thanks for reporting this. I followed the steps and both codes for Auth is working. I was able to run the app by using this snippet:

import React, { useEffect } from 'react';
import { browserLocalPersistence, initializeAuth, onAuthStateChanged} from 'firebase/auth';
import { initializeApp} from 'firebase/app'
function App() {
  let firebaseApp;
  let firebaseAuth;

  useEffect(() => {
    let firebaseConfig = {
      apiKey: "",
      authDomain: "",
      projectId: "",
      storageBucket: "",
      messagingSenderId: "",
      appId: "",
      measurementId: ""
    };
    firebaseApp = initializeApp(firebaseConfig);    
    firebaseAuth = initializeAuth(firebaseApp,{persistence: browserLocalPersistence});

    onAuthStateChanged(firebaseAuth, (user) => {
      console.log('user', user);
      if (user) {
        // User is signed in, see docs for a list of available properties
        // https://firebase.google.com/docs/reference/js/firebase.User
        const uid = user.uid;
        console.log("User is signed in");
      } else {
        // User is signed out
        console.log("User is signed out");
      }
    });
  }, []);
}

Let me know if you're still experiencing the issue.

@arneesh
Copy link

arneesh commented Sep 10, 2021

@jbalidiong are you using client-side rendering? And development mode? I am facing this issue in production mode after running build, on dev mode without ssr it works fine.

@archevis
Copy link

archevis commented Sep 12, 2021

Facing the same issue with Angular Universal SSR:

@firebase/auth: Auth (9.0.0): INTERNAL ASSERTION FAILED: Expected a class definition

All works fine in dev mode without SSR (that is, client-side rendering).

EDIT: No idea why it says 9.0.0, my package.json says "firebase": "^9.0.2"

EDIT 2: Initially I got the following error during server-side rendering when upgrading to firebase 9:

ERROR Error: Uncaught (in promise): ReferenceError: navigator is not defined
ReferenceError: navigator is not defined
    at Object.areCookiesEnabled (...)
    at SwitchMapSubscriber.<anonymous> (...)
    ...

So I tried adding a domino implementation to make navigator and other globals available:

const win = domino.createWindow(template);
global.window = win;
global.document = win.document;
global.navigator = win.navigator
...

Could the problem be domino related?

@bramvanneerven
Copy link
Author

I am currently using the following workaround.

import { 
  browserLocalPersistence,
  inMemoryPersistence,
  indexedDBLocalPersistence,
  initializeAuth,
} from 'firebase/auth';

const auth = initializeAuth(app, {
  persistence:
    typeof window === 'undefined'
      ? inMemoryPersistence
      : [indexedDBLocalPersistence, browserLocalPersistence],
});

@jbalidiong
Copy link
Contributor

@bvanneerven, I'll try and replicate this by following the additional information provided by @arneesh and @archevis. If I can replicate the issue, I can have a better look into it.

@arneesh
Copy link

arneesh commented Sep 13, 2021

For the time being, I am using @bvanneerven 's workaround.

@archevis
Copy link

@bvanneerven, I'll try and replicate this by following the additional information provided by @arneesh and @archevis. If I can replicate the issue, I can have a better look into it.

Just for the record, I'm using @anguar/fire

Let me know if there is anything I can do to help.

@jbalidiong
Copy link
Contributor

Unfortunately, I still wasn’t able to replicate the issue when running using the production mode. Please share a minimal, but complete sample of a project that I can run locally.

@archevis
Copy link

archevis commented Sep 14, 2021

Unfortunately, I still wasn’t able to replicate the issue when running using the production mode. Please share a minimal, but complete sample of a project that I can run locally.

https://github.com/archevis/firebase-issue-5475

I've done some more investigating, and from what I've found it looks like the errors are linked to Analytics. But as mentioned, I'm using @angular/fire and the problem may reside here for all I know.

In order to test the example project:

  1. add a proper web app Firebase config to both files in src/environments/
  2. run npm run start from the project root directory
  3. visit http://localhost:4200 to see client-side rendering working
  4. run npm run test:ssr from the project root directory
  5. visit http://localhost:4000 to see server-side rendering fail

(Note that I have also deleted .firebaserc and firebase.json, but that shouldn't make any difference for this test.)

@hsubox76
Copy link
Contributor

hsubox76 commented Sep 15, 2021

The short answer is that browserLocalPersistence isn't available in Node, so we set that export to an error in the Node build. And SSR and test environment configs tend to look at the main field in a dependency's package.json when importing that dependency, which usually points to the dependency's Node build, instead of the browser field, which points to the browser build.

If you console.log the value of browserLocalPersistence right before the error, I think you'll find that it is itself a FirebaseError with the message Firebase: Error (auth/operation-not-supported-in-this-environment). This is the value it is set to in the Node bundle.

We usually advise users to modify their SSR (or test) configuration so that it picks up the browser field instead of the main field. How to do this can vary a lot depending on your build setup, so I'm not sure how Angular Universal does it, you may want to consult someone who is more familiar with it if you can't figure it out. In webpack config files it usually involves something like:

resolve: {
      mainFields: ["browser", "main"]
    },

I do think we should probably find a better way to log this error, since the useful message ("Firebase: Error (auth/operation-not-supported-in-this-environment)") isn't visible unless you think to console.log the browserLocalPersistence import.

For myself/team, the export is:

export const browserLocalPersistence = NOT_AVAILABLE_ERROR;

It just exports the error object. I think that perhaps initializeAuth should throw it when it's passed to it?

@Feiyang1
Copy link
Member

It would be nice if browserLocalPersistence(and other persistence implementations unsupported in Nodejs) can gracefully failover to inMemoryPersistence in Nodejs. It will make SSR much easier by making firebase code isomorphic in browser and node, which is the direction we'd like to go.

@sam-gc @jamesdaniels WDYT?

@sam-gc
Copy link
Contributor

sam-gc commented Sep 16, 2021

Seems reasonable to me. That's essentially what happens if you use getAuth() instead of initializeAuth() (it inits with in-memory). It's basically a no-op which is what we'd want

@firebase firebase locked and limited conversation to collaborators Oct 23, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants