I'm using the Facebook JS sdk, and I have created a new App today.
Everything is configured properly.
Using init function like:
window.fbAsyncInit = function() {
FB.init({
appId : 'xxxx', // App ID
status : false,
version: 'v2.0',
cookie : true,
xfbml : false // parse XFBML
});
};
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/pl_PL/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
but I have an error:
"Uncaught Error: init not called with valid version "
Was trying also other versions like: 2.1, 2.2 and still no luck.
What am I doing wrong here?
**Disclaimer - This is purely speculation. Seems to have solved my problem.
I've had this issue on a recent project. I think this is a latency issue. The Facebook SDK requires that <div id="fb-root"></div> be on the page. This should be the first thing after the opening body tag. After this, you may see your initialization code.
For me, this issue was not consistent. I would occasionally see the bug and sometimes I would not. Thus, my conclusion of it being a latency problem. If the SDK cannot find the fb-root, then it must create one. Herein, is where I believe the latency issue exists.
Try adding this just after your opening body tag, but before your FB.init({});.
<div id="fb-root"></div>
This seems to have solved the issue for me and will hopefully help others as well. The v1.0 documentation discusses the reason for fb-root, but the v2.0 docs make no mention of the item, likely because the init script will add it for you if it does not find it.
I got it working by using all.js instead of sdk.js.
In your case, it would look like:
js.src = "//connect.facebook.net/pl_PL/all.js";
instead of
js.src = "//connect.facebook.net/pl_PL/sdk.js";
Add &version=v2.0 to js.src, as follows:
(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/sdk.js#xfbml=1&version=v2.0";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
This problem plagued me for a while. I tried many of the ideas listed here such as changing the version number and moving/removing the fb-root.
What is finally working well for me is to delete the entire window.fbAsyncInit function and specify the init properties in the hash of sdk.js. For example:
<script type="text/javascript">
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "https://connect.facebook.net/en_US/sdk.js#version=v2.2&appId=12345&status=true&cookie=true&xfbml=true";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
</script>
Of course you may omit a parameter to use its default value.
I can't find this approach documented anywhere so use it at your own risk. Luckily I was upgrading an older site from v1.x to v2.x and it used this technique when loading all.js.
i replaced this
js.src = "//connect.facebook.net/en_US/sdk.js";
with this
js.src = "//connect.facebook.net/en_US/all.js";
and worked :)
This was the only fix that would eliminate the error 100% of the time.
You can recreate this error by deleting your FB.init. Which confirms that although the sdk.js had been loaded and the FB namespace existed, FB.init hadn't been called by the time we were trying to use FB methods elsewhere in our scripts.
So we need to ensure that FB.init has been called. I used a similar approach to this answer:
if (typeof(fbApi) === 'undefined') { fbApi = {}; }
fbApi = (function () {
var fbApiInit = false;
var awaitingReady = [];
var notifyQ = function() {
var i = 0,
l = awaitingReady.length;
for(i = 0; i < l; i++) {
awaitingReady[i]();
}
};
var ready = function(cb) {
if (fbApiInit) {
cb();
} else {
awaitingReady.push(cb);
}
};
window.fbAsyncInit = function () {
FB.init({
appId : '<?php echo esc_js( $facebook_app_id ); ?>',
status : true,
cookie : true,
xfbml : true,
version: 'v2.0'
});
fbApiInit = true;
notifyQ();
};
return {
/**
* Fires callback when FB is initialized and ready for api calls.
*/
'ready': ready
};
})();
(function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {
return;
}
js = d.createElement(s);
js.id = id;
js.src = "//connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
Then, elsewhere, any reference to FB can be made like this:
fbApi.ready(function() {
FB.XFBML.parse($("#fb-comments"));
});
This was happening to me too with great inconsistency. Somewhere my hunch said, it is got to be a timing issue. Further debugging, found out an error in developer console by manually executing "FB.login()". The error said, "init not called with valid version".
In my case, I was adding //connect.facebook.net/en_US/sdk.js as a script tag in the header of the html page and the window.fbAsyncInit came in another file just after that. This pointed to me as a timing issue and hence I swapped these 2 script tags. Now once I had included window.fbAsyncInit before including //connect.facebook.net/en_US/sdk.js, the problem was gone. Hope this helps others.
For single page applications (React in my case)
In single page applications you have less control about the order in which the code will run. Sometimes the script will have loaded by the time you call your code, sometimes not.
To make it work regardless of whether the facebook script has already loaded or not, I do a check whether the FB global variable is already defined at the moment of running the code. If so, I just do a normal initialize, otherwise I provide the callback.
This is my code:
export function initializeFacebookSdk() {
/* Asynchronous flow: if the global 'FB' variable is still undefined,
then the facebook script hasn't loaded yet, in that case, provide
a global callback that will be called by the facebook code. If the
variable is already present, just call the code right away and forget
about the callback. */
if(window.FB === undefined) {
console.log('FB undefined -> provide callback');
window.fbAsyncInit = function() {
initialize();
};
}
else {
console.log('FB defined -> call init right away');
initialize();
}
function initialize() {
window.FB.init({
appId : '492331311256888',
cookie : true,
xfbml : true,
version : 'v3.2'
});
}
}
In my html file I just provide the script given by facebook, and in my code I can call initializeFacebookSdk() wherever and whenever I want:
<!DOCTYPE html>
<html lang="en">
<head>
<title>My application</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<script>
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "https://connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
</script>
<div id="root"></div>
</body>
</html>
Try this code:
setInterval(
function() { FB.api('/me/',
function(r) { console.log('response: ', r); })
}, 5000);
I noticed then when I'm trying get info fb still be not initialized.
I fixed it by adding my initialization code to end of:
FB.getLoginStatus(function(response) { init(); });
I resolved this error by loading the script on document ready instead of document load.
For example, this gave the error about 10% of the time:
$(window).load(function(){
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
});
whereas this works all the time:
$(window).ready(function(){
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
});
Watch out when you call FB api after init. Init seems synchronous, but window.fbAsyncInit is not, so you have to wait for its execution. My example to reproduce is in phonegap browser platform, but after I checked the facebook plugin code I'm sure it can be reproduced in pure javascript environment also.
This was my code that fires the error:
if (window.config.debug_mode) {
facebookConnectPlugin.browserInit('xxxxxxxxx', function() {
});
}
// getLoginStatus is wrong here as window.fbAsyncInit is not yet completed
facebookConnectPlugin.getLoginStatus(function(status) {
alert('logged: ' + JSON.stringify(status));
}, function(error) {
alert('error: ' + JSON.stringify(error));
});
Here is how I fixed it:
if (window.config.debug_mode) {
facebookConnectPlugin.browserInit('xxxxxxxxx', function() {
facebookConnectPlugin.getLoginStatus(function(status) {
alert('logged: ' + JSON.stringify(status));
}, function(error) {
alert('error: ' + JSON.stringify(error));
});
});
}
I'm sure that the following code will throw in browser, but I don't have time to verify it:
window.fbAsyncInit = function fbAsyncInit () {
version = version || 'v2.6'
FB.init({
appId: appId,
xfbml: false,
version: version
})
}
// now calling any FB function here will rise this error
We use our own API that does this:
_loadFacebookApi: function(callback) {
logger.info('_loadFacebookApi');
(function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {
return;
}
js = d.createElement(s);
js.id = id;
js.src = "https://connect.facebook.net/en_US/sdk.js";
}(document, 'script', 'facebook-jssdk'));
var fbScript = window.document.getElementById('facebook-jssdk');
fbScript.onload = fbScript.onreadystatechange = (function() {
logger.info('fbScript onLoad');
window.FB.init({
version: 'v2.1',
appId: '',
channelUrl: '/fbchannel.html',
status: false,
cookie: true,
xfbml: true,
logging: true,
oath: true
});
this.dispatch(constants.FACEBOOK_INIT_SUCCESS);
if(callback){
callback();
}
}.bind(this));
}
I had the same problem when I tried to embed a simple Facebook post in an article I was writing.
<div id="fb-root"></div><script>(function(d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js = d.createElement(s); js.id = id; js.src = "//connect.facebook.net/en_US/sdk.js#xfbml=1&version=v2.3"; fjs.parentNode.insertBefore(js, fjs);}(document, 'script', 'facebook-jssdk'));</script><div class="fb-post" data-href="https://www.facebook.com/feyenoord/posts/10153224326681816:0" data-width="500"><div class="fb-xfbml-parse-ignore"><blockquote cite="https://www.facebook.com/feyenoord/posts/10153224326681816:0"><p>Een teleurstellende middag in De Kuip. Ook ADO Den Haag bleek vanmiddag te sterk voor Feyenoord. http://bit.ly/1UA3ZxZADO Den Haag too strong for Feyenoord. http://bit.ly/1UA6rEN</p>Posted by Feyenoord Rotterdam on Sunday, January 31, 2016</blockquote></div></div>
When I debugged the Facebook sdk.js I saw that the .getVersion returned "undefined" and thus not rendering the widget.
Apparently Facebook can't handle passing query parameters seperated by & instead of & when loading the sdk.js. I had changed my code to & for validation reasons.
Works: js.src = "//connect.facebook.net/en_US/sdk.js#xfbml=1&version=v2.3";
Doesn't Work: js.src = "//connect.facebook.net/en_US/sdk.js#xfbml=1&version=v2.3";
The error happened each time I redirected to a page (Edge Browser) that had a fb-page plugin.
If I refreshed the page it would work. If I got there through a hyperlink it would throw the error.
Fixed it by adding sdk.js?d=" + new Date().toISOString(); to the script.
(function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) { return; }
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/sdk.js?d=" + new Date().toISOString();
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
You are using the cordova-plugin-facebook4 plugin, and that is a custom error message that means that the init hasn't finished when the facebook api function is called. Since the plugin does not give a waitForInitialize using setTimeout and then retrying the api method is the best bet.
var retryFunc = (iteration) => {
return new Promise((s, f) => facebookConnectPlugin.getLoginStatus(s, f))
.then(authentication => authentication.status === 'connected')
.then(isLoggedIn => {
/* Your Code Here */
})
.catch(failure => {
console.log(`Waiting for Facebook Init. Iteration: ${iteration || 0}`);
if((iteration || 0) < 10) {
return new Promise((s, setTimeout(() => s(), 1000)
.then(() => retryFunc(null, (iteration || 0) + 1);
}
else { return Promise.reject({Error: 'Failed to check login status.', Detail: failure}); }
});
};
retryFunc();
/* Or replace getLoginStatus with your api call. */
Error Message
Additional info
SINGLE INCLUDE—make sure the Facebook JavaScript API isn't included more than once on your page.
(This was my problem)
Make sure you're using https:// in the URL
js.src = "https://connect.facebook.net/en_US/sdk.js";
I would not have believed this either, but the only difference between what Facebook has in their current sample code and what I have is https:// instead of // for the url.
Updating to be https:// seems to have fixed it for me and I cannot duplicate the error.
Also if you're doing any checks elsewhere in your code to see if FB is defined make sure to check if (window.FB) and not if (FB) or you will get an error.
// call after manually adding DOM nodes containing FB widgets
if (window.FB)
{
window.FB.XFBML.parse()
}
If you're using typescript you need to add something like this:
interface Window
{
FB: IFacebook;
}
interface IFacebook
{
XFBML: any;
ui: any;
getLoginStatus(callback: (response: { status: string }) => any);
login(callback: (response) => any, options: any);
logout(callback: () => any);
Event: any;
api(url: string, callback: (response: any) => any);
}
I had the same problem, and I think I found the root cause!
Root cause
In my case, we were injecting FB SDK dynamically to our customer's website. However, some of our customers were already added FB SDK via other plugins. Those plugins have different app id and version.
So depending on latency some plugins call init before/after ours
Solution
If you're the owner of the site where you're injecting the SDK, make sure no other plugins are injecting FB SDK and calling init different version and app id
If you don't own the site, then at least try to inject the SDK before anyone else and prefer not async
I also reported the same to FB. They told not to call init separately, pass init params directly in the rule. I've attached the code that I use:
if (!document.getElementById("fb-root")) {
// create div required for fb
const fbDiv = document.createElement("div");
fbDiv.id = "fb-root";
document.body.appendChild(fbDiv);
// Run any script after sdk is loaded
window.fbAsyncInit = () => {
//
};
// inject sdk.js
(function(d, script) {
script = d.createElement("script");
script.type = "text/javascript";
script.async = true;
script.src =
"https://connect.facebook.net/en_GB/sdk.js#xfbml=1&version=v3.2&appId=" +
process.env.REACT_APP_FB_APP_ID +
"&autoLogAppEvents=1";
d.getElementsByTagName("head")[0].appendChild(script);
})(document);
}
In my case it was an api version problem, as suggested by the error message.
Let the version loaded in the FB script tag match the one in your FB initialization script, by specifing the same when loading the sdk (in the hash), for instance for version 4.0:
<script src="https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v4.0"></script>
and in your script like:
window.fbAsyncInit = function() {
FB.init({
appId: XXX,
autoLogAppEvents: true,
xfbml: true,
version: 'v4.0' //<------------- same version
});
};
window.fbAsyncInit = function() {
FB.init({
appId : 'xxxx', // App ID
status : false,
version: 'v2.0',
cookie : true,
xfbml : false // parse XFBML
});
};
There is error version: 'v2.0',
This is not valid code
When my click handler calls logIn() function on a client, I see a FB popup and a record being created in User collection, but callback methods are never called. Instead, I see the following in JS console
Uncaught TypeError: Cannot read property 'getTime' of null parse-1.2.18.min.js:3
Here is the code on my page
Setting up FB API
<script>
window.fbAsyncInit = function() {
Parse.FacebookUtils.init({
appId : 757503280935086,
xfbml : true,
version : 'v2.0'
});
};
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
</script>
Calling login method
$scope.signupFB = function() {
Parse.FacebookUtils.logIn(null, {
success: function(user) {
//never get here
$timeout(function() {
$rootScope.theUser = user;
$location.path("/properties");
});
},
error: function(user, error) {
$scope.error = "User cancelled the Facebook login or did not fully authorize.";
}
});
}
The FB app has a website "Platform" enabled.
Next time I tried I saw
Uncaught Error: Setting authResponse is not supported
in JS console.
NOTE: This fix is no longer required (and instead will actually break it) as Facebook fixed the API call to return the date in the old string format.
Facebook added v2.0 of the API recently, unfortunately they broke Parse. In particular Parse uses a very strict rule for reading the date from the Facebook response.
A workaround is to download the parse-1.2.18.js file, and update the Parse._parseDate function, then load that JS file into your site and change your pages to use that instead of the current version:
Parse._parseDate = function(iso8601) {
var regexp = new RegExp(
"^([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,2})" + "T" +
"([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})" +
"(.([0-9]+))?" + "Z$");
Update it to this:
Parse._parseDate = function(iso8601) {
var iso8601 = iso8601.split(“+”)[0] + “Z”;
var regexp = new RegExp(
"^([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,2})" + "T" +
"([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})" +
"(.([0-9]+))?" + "Z$");
Basically it is just stripping off any “+00:00” from the end and adding the “Z” back on so that it works again.
You could make it more robust (in case Facebook revert to the old date format) by using this instead:
var iso8601 = iso8601.split(“+”)[0].split(“Z”)[0] + “Z”;
That way if the “Z” gets put back on we grab everything before it and don’t break.
There’s a bug logged in the Facebook bug tracker that also shows an updated regexp that will work with both, I don’t have the link handy though.
UPDATE: Also ensure you're using the right version of the API.
If you follow the instructions on Facebook now, they want you to have a section like this:
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
Note that if you are using the sdk.js you'll need to pass a version parameter to the init call, which for Parse will end up looking like this:
window.fbAsyncInit = function() {
Parse.FacebookUtils.init({
appId : yourAppId,
xfbml : true,
version : 'v1.0'
});
};
We are explicitly setting the version to 1.0 until such time as Parse update their code to handle 2.0.
The problem comes from using the v2 facebook api.
Switching to the old version with Timothy's fix works.
window.fbAsyncInit = function() {
Parse.FacebookUtils.init({
appId : '' // Facebook App ID
});
};
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/all.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
Notice including all.js not sdk.js