I just got the awesome error “fb.login called before fb.init” and remembered all the things i learned @knallgrau why this error could happen but found no solution. Here is why i still got it. And why it took me hours to find it.

what i tried

If you follow the instructions on https://developers.facebook.com/docs/reference/javascript/ and copy paste facebook’s initialization and loading code into one of your closure-classes you’ll get the typical error mentioned above.

Unfortunately fb.init fails silently not telling you why it could not initialize. So i remembered the reasons why i got this error earlier and checked:

  • if i included all.js more than once
  • if the app id was wrong
  • if the app settings were incorrect (no trailing “/”, wrong domain-name, wrong sandbox settings, etc, etc)

nothing was wrong with that. i even wrote the app id into the init-command literally. did not work.

what was wrong

I was desperate. In google closure to preserve names for externs you have to store the function via array access:

window['fbAsyncInit'] = function() {
   FB.init({appId: 1234567890});

This was the only difference i made from copy pasting it to my closure class (ok in the code above i removed some lines). Finally i figured i could check if the correct function is written into the global fbAsyncInit. So i went to my console (had to clear millions of lines of hopeless debugging attempts) and typed “window.fbAsyncInit”. And what did i see???

Google Closure played with my code!

function $window$fbAsyncInit$() {
    FB.init({$appId$:1234567890, $channelUrl$:"/channel.html", status:!1, $xfbml$:!0, $oauth$:!0, cookie:!0, $logging$:!0});

of course $appId$ resolved to ‘appId’, but this was the exact problem!

The solution

So the next step was easy: use string literals for my plain object!

window['fbAsyncInit'] = function() {
   FB.init({'appId': 1234567890});

worked like charm.