Pcall not working as expected?

Hello!

So I’m having an issue with pcall where it is still spewing out the error message in certain situations. Instead of it showing an error message, I want to handle it accordingly.

For you to gain a better understanding of what is happening, I’ve constructed two test scripts.

Script A:
image

Script B:

With Script A, it is working perfectly. No error is displayed in the console regarding “hello” not being able to be converted to JSON.

Script B, on the other hand, displays the error in the console regarding “hello” not being able to be converted from JSON. It is like the HTTP request is only exempt from the error message from being displayed.

Both pcalls are returning “false”, with the appropriate error message for the “response”.

I’m after try/catch functionality like other languages. Is there a way to have Script B functioning like Script A without two separate pcalls? It makes the code look messy.

3 Likes

Since HttpService:RequestAsync() is a yielding function due to its nature of sending a web request, you need to use ypcall(), or “yield” pcall, instead. The reason why Script A works is because HttpService:JSONDecode() does not yield.

The error from Script B isn’t coming from :RequestAsync though. It’s coming from :JSONEncode.

Did you try what I said?

1 Like

Yes. It still behaves in the same way as stated in the original post.

ypcall and pcall are the same internally.

I believe I know what the cause for this is, I’ll have a look and confirm this.

2 Likes

I could’ve sworn there was something about not being able to yield inside of a normal pcall, so they made ypcall

In standard Lua you are unable to yield inside of a pcall, therefore ypcall was created, some time later pcall was changed to be the same as ypcall.


I have looked into this some more and know what is going on. Roblox uses continuations which are a way of specifying what to do after a thread terminates. If a thread yields, those continuations are passed along each time the thread resumes.

continuations do not consider error suppression, as such when a thread such as pcall is resumed, the errors will be displayed in the output after it has yielded once.

local success, result = pcall(function ()
	wait()
	error()
end)

print(success, result)

This is related to a bigger issue which I am hoping to fix at some point in the future, for now you will need to wrap each individual statement inside of a pcall to suppress the errors.

8 Likes

Ah. Thank you for looking into this for me. :slight_smile: Looks like I will have to use individual pcalls after all.

I found that behavior to happen to coroutines too:

> local c = coroutine.create(function() error() end) print(coroutine.resume(c))
false nil
> local c = coroutine.create(function() wait() error() end) print(coroutine.resume(c))
true
10:29:40.441 - Error occurred, no output from Lua.
10:29:40.455 - Stack Begin
10:29:40.456 - Script 'local c = coroutine.create(function() wait() error() end) print(coroutine.resume(c))', Line 1
10:29:40.456 - Stack End
1 Like

This is for the same reason, and part of the bigger issue I mentioned.

3 Likes

Ohhhh, I was unaware of the change. So I was kinda right, just not caught up with the functionality haha