Fail to login. Cannot read properties of undefined (reading 'bloks_payload')
Hi there! Today, I encountered an error when trying to log in through the IOS client.
I attached a screenshot of the error message for reference
I have a working code on Firebase Functions that I've been using without any issues when running it locally. However, when I tried to use it with IOS -> Firebase Functions -> threads.js client.login, something went wrong. Could you kindly assist me with this issue? Thank you!
P.S. The same error persists even when the username and password are hardcoded.
Also, I've attached a screenshot of the working code on Firebase Functions for your reference
cc https://github.com/stevenlafl/threads-web-client/issues/11
interesting because I can't actually replicate this. could you console.log what text is giving you in Bloks.js? if it's sensitive information, remove it. I suspect that you might be getting an error
Are you in the EU or in the UK perchance? The app is blocked in the EU and the UK is having issues right now. I think part of these answering these reports should be asking the location now @elijah-wright
well I start out by assuming that because you can't have a threads account if you live in the EU. but if the UK is having issues then that might be important to mention
I have same issue
2023-07-14T02:29:55.730172+00:00 app[web.1]: TypeError: Cannot read properties of undefined (reading 'bloks_payload') 2023-07-14T02:29:55.730186+00:00 app[web.1]: at parseBloksResponse (/app/node_modules/@threadsjs/threads.js/src/util/Bloks.js:29:42) 2023-07-14T02:29:55.730187+00:00 app[web.1]: at Client.login (/app/node_modules/@threadsjs/threads.js/src/index.js:131:17) 2023-07-14T02:29:55.730187+00:00 app[web.1]: at process.processTicksAndRejections (node:internal/process/task_queues:95:5) 2023-07-14T02:29:55.730187+00:00 app[web.1]: at async /app/server.js:17:5
Perhaps you (@elijah-wright, @stevenlafl) need this to fix the issue. I can't help much because I have a lot of work, but good luck. https://github.com/sooluh/bloks-parser
could you console.log what text is giving you in Bloks.js?
I'm seeing the similar issue. My code (written in Golang) runs fine on my Mac, but fails running on Google Cloud Functions. I'm suspecting Threads service restricts login requests from public cloud (or maybe, from IP addresses, whose locations are unidentifiable).
any solution here?
@tyagihas is your function located in the EU? if not, it's probably blocking IP addresses from known cloud servers
@tyagihas is your function located in the EU? if not, it's probably blocking IP addresses from known cloud servers
I am able to run it in AWS Lambda. However I only tested it having a token already. Try logging in the US and then reusing that token.
I've found that threads.js doesn't properly handle:
- Attempted login with bad user
- Attempted login with bad password
- Other assorted authentication errors
In my investigation, I wrote a peggy parser that understands the Bloks payload well enough to process it into arrays (which you then need to walk):
parseBloks.js
const { generate } = require('peggy');
const { relative, resolve } = require('path');
const BLOKS_GRAMMAR = `
{
// Allows you to provide a blok processor by passing the "processBlokModule" argument
const processBlok = options.processBlok ?? ((name, args) => [name, ...args]);
}
Blok
= _ "(" _ name:ClassName _ args:("," _ next:Arg { return next; })* _ ")" _ {
return processBlok(name, args);
}
ClassName
= head:$Identifier tail:("." next:$Identifier { return next; })* { return [head, ...tail].join('.'); }
Identifier
= [a-zA-Z_] [a-zA-Z_0-9]*
Arg
= Blok
/ Number
/ String
/ Null
/ Boolean
Number
= n:$[0-9]+ { return parseInt(n); }
String
= '"' content:StringChar* '"' { return content.join(''); }
Null
= "null" { return null; }
Boolean
= "true" { return true; }
/ "false" { return false; }
StringChar
= [^"\\\\]
/ "\\\\" "\\"" { return '"'; }
/ "\\\\" "\\\\" { return '\\\\'; }
/ "\\\\" "b" { return '\\b'; }
/ "\\\\" "f" { return '\\f'; }
/ "\\\\" "r" { return '\\r'; }
/ "\\\\" "t" { return '\\t'; }
/ "\\\\" "b" { return '\\b'; }
/ "\\\\" "u" hex:$[0-9][0-9][0-9][0-9] { return String.fromCodePoint(parseInt(hex, 16)); }
/ "\\\\" ch:[^\\\\bfrtbu] { return ch; }
_ = [ \\r\\n\\t]*
`;
function createBloksParser(processors = {}) {
const { parse } = generate(BLOKS_GRAMMAR);
const processBlok = (name, args) => {
if (typeof processors[name] === 'function') {
return processors[name](name, args);
}
if (processors['@']) {
return processors['@'](name, args);
}
return [name, ...args];
};
return (bloks_payload) => parse(bloks_payload, { processBlok });
};
module.exports = {
createBloksParser
};
You then create and use it:
const bloks_payload = `
(bk.action.map.Make,
(bk.action.array.Make, "login_type", "login_source"),
(bk.action.array.Make, "Password", "Login")
)
`;
const parseBloks = createBlokParser();
const bloks = parseBloks(bloks_payload);
and the result will be:
["bk.action.map.Make",
["bk.action.map.Make", "login_type", "login_source"],
["bk.action.map.Make", "Password", "Login"]
]
Anyway, what I've found trawling through the parsed payloads is that, for the login responses at least, you can detect an error by searching for a bk.action.qpl.MarkerAnnotate blok with a child of ["bk.action.array.Make", "generic_error_dialog"]; in the same response there will be a ig.action.cdsdialog.OpenDialog. The string children of the OpenDialog's first bk.action.tree.Make child will be the error heading and message.
To search for a blok by name:
const isBlok = bloks && typeof bloks === 'object' && Array.isArray(bloks) && typeof bloks[0] === 'string';
const findBloksByName = (name, blok) => {
if (!isBlok(blok)) return null;
if (blok[0] === name) return [blok];
return blok.slice(1).reduce((instances, child) => {
instances.push(...findBloksByName(name, child);
return instances;
}, []);
};
To get a blok's string content:
const blokTextContent = (blok) => blok.slice(1).filter(item => typeof item === 'string');
Putting it all together:
const getBlokError = (blok) => {
const candidates = findBloksByName('bk.action.qpl.MarkerAnnotate', blok);
const hasError = candidates.some(candidate => (
return candidate.some(child => (
child.length === 2
&& child[0] === 'bk.action.array.Make'
&& child[1] === 'generic_error_dialog'
))
));
if (!hasError) return null;
const dialog = findBloksByName('ig.action.cdsdialog.OpenDialog')[0];
const [title, message] = blokTextContent(dialog);
return { title, message };
};
Admittedly, I haven't done all the legwork to figure out what bloks contain JSON response data, however, I did find that during the login flow, bk.action.caa.PresentTwoFactorAuthFlow and bk.action.caa.HandleLoginResponse play key roles.
The parser is also made so you can create your own handlers for each blok type when generating the parser, e.g.,
const parse = createBlokParser({
"bk.action.array.Make": (_, entries) => entries,
"bk.action.i32.Const": (_, [value]) => parseInt(value),
"bk.action.bool.Const": (_, [value]) => !!value,
});
const payload = '(bk.action.array.Make, (bk.action.i32.Const, 42069), "nice", (bk.action.bool.Const, true))';
console.log(JSON.stringify(parse(payload)));
[42069, "nice", true]
The special @ processor will allow you to have more custom behavior than just (name, args) => [name, ...args], which is the default. This is useful in that you could have something like,
/*...*/
"@": (name, args) => {
console.warn(`Unknown blok: ${name} (\n ${JSON.stringify(args, null, 2).split('\n').join('\n ')}\n)`);
return [name, ...args];
},
/*...*/
So, like, for debugging, that'll report when it comes across a block type you haven't handled yet.
I hope this can help you with making threads.js more reliable!
@Fordi it's not necessarily about not being able to handle those things, but I just haven't had the ability to be able to go in and see what some of the bloks being returned are. I'd like to be able to make a library to parse this stuff tho, that's definitely something I want to do. but I also have to write typings. so it's also managing some of this stuff
:+1: Makes sense. Here's hoping the parser is useful to you.
On that subject, I almost forgot. Sample payloads! Took me a second to redact them so you wouldn't have my auth tokens.
success.bloks.txt 2fa-req.bloks.txt bad-account.bloks.txt bad-password.bloks.txt
awesome, thanks for this. I'll definitely see what I can do but there's a lot to be done. the idea I have right now is to make this a monorepo with the bloks parser because this library is tied to bloks parsing
@elijah-wright Something strange happened when I tried to debug the text in Bloks.js. I forked and added console logs to debug in Google Cloud Console. Everything started to work as expected. The magic of console.log xD @stevenlafl, no Im not from UK or EU, but Im from Ukraine. We have no problems with the Threads access.
I changed my server from Heroku to Cyclic it's resolved
Done.
https://www.npmjs.com/package/@fordi-org/bloks-parser
https://github.com/Fordi/bloks-parser
I'll add you as a contributor.
[Edit: also done. To the repo and to the npm package.]
@serhaterfidan its a floating bug, so I think it doesn matter which server you are using... Im using firebase and it always unexpected... Now I have the same problem.
@elijah-wright that what's I get when trying to login
@serhaterfidan its a floating bug, so I think it doesn matter which server you are using... Im using firebase and it always unexpected... Now I have the same problem.
I think it's about Threads endpoints limitations or restrictions Cyclic is down now also
I've gotten that wait a few minutes thing before, I actually don't know how to fix it lol. it's just one of those things that meta has
@elijah-wright Idk too. I've been waiting for several hours... And nothing. Im still see the "Wait for a few minutes, please" error 😭
I switched the environment and was able to run my Golang code on Google Cloud Functions with a fixed external IP address (ap-northeast1, Tokyo).
I think some of you are facing IP address ban issue with Instagram. They may ban your IP address from several reasons. I haven't confirmed with the support, but for my case, It's probably because I tried to login with multiple accounts from a single IP address.
You may reach out to the support and ask them to remove the IP address from the blocked list (I haven't done this yet).
Hey @tyagihas, I think your issue can be solved by implementing a proxy. I just opened a new issue on #74.
no longer applicable in v2