Google Firebase Auth in Unity: How to read error codes - c#

When using the Google Firebase Authentication plugin in Unity, how do you read error codes of faulted requests?
For example, within this code:
auth.SignInWithEmailAndPasswordAsync(email, password).ContinueWith(task => {
if(task.IsFaulted){
Debug.Log("ERROR ENCOUNTERED: " + task.Exception);
return;
}
if(task.IsCompleted){
// Success!
}
});
You can see that if an error occurs I can log the exception out, which prints the following:
ERROR ENCOUNTERED: System.AggregateException: Exception of type 'System.AggregateException' was thrown.
Firebase.FirebaseException: There is no user record corresponding to this identifier. The user may have been deleted.
That's very human-readable, but not very elegant to put into a switch statement. Is there any way for me to cast the task.Exception to be a FirebaseException so I can grab the error code? And is there a list of these error codes somewhere? I can find the documentation for the FirebaseException, but the error codes aren't there. Thanks for the help!
Edit:
So while I am still hoping for an answer, I've come to think that Google expects developers to use blanket error statements based on the context of the request. For example, when failing to sign in with an email and password (as in the above code), we should use the common statement of "Email or password is incorrect." The problem with that is that I can't let the user know the difference between them providing the incorrect details versus them entering an email which doesn't have an account associated with it at all.

Hopefully you've solved this by now but I've just come across the exact same problem and I'll share my solution:
According to MSDN, System.AggregateException is a representation of one or more errors that may occur during the task execution.
Therefore, you'll need to loop through the InnerException(s) presented by the AggregateException, and look for the suspected FirebaseException:
Retrieving the FirebaseException:
AggregateException ex = task.Exception as AggregateException;
if (ex != null) {
Firebase.FirebaseException fbEx = null;
foreach (Exception e in ex.InnerExceptions) {
fbEx = e as Firebase.FirebaseException;
if (fbEx != null)
break;
}
if (fbEx != null) {
Debug.LogError("Encountered a FirebaseException:" + fbEx.Message);
}
}
Getting the Error Code:
Wish I could help here but I haven't found anything - these aren't documented within the official API, AFIK. The only reference states: "If the error code is 0, the error is with the Task itself, and not the API. See the exception message for more detail."

I encountered the same dilemma trying to find out which error code I get from Firebase and display appropriate message for the user.
The correct way to read the Firebase Exception is with this function I created:
bool CheckError(AggregateException exception, int firebaseExceptionCode)
{
Firebase.FirebaseException fbEx = null;
foreach (Exception e in exception.Flatten().InnerExceptions)
{
fbEx = e as Firebase.FirebaseException;
if (fbEx != null)
break;
}
if (fbEx != null)
{
if (fbEx.ErrorCode == firebaseExceptionCode)
{
return true;
}
else
{
return false;
}
}
return false;
}
And you can use it like this:
auth.SignInWithEmailAndPasswordAsync("test#gmail.com", "password").ContinueWith(task => {
if (task.IsCanceled)
{
Debug.LogError("SignInWithEmailAndPasswordAsync was canceled.");
return;
}
if (task.IsFaulted)
{
if(CheckError(task.Exception, (int)Firebase.Auth.AuthError.EmailAlreadyInUse))
{
// do whatever you want in this case
Debug.LogError("Email already in use");
}
Debug.LogError("UpdateEmailAsync encountered an error: " + task.Exception);
}
}
Here is some more code samples from firebase:
https://github.com/firebase/quickstart-unity/blob/master/auth/testapp/Assets/Firebase/Sample/Auth/UIHandler.cs
I got the answer from this thread:
https://github.com/firebase/quickstart-unity/issues/96
I hope this will help someone. All the best!

Related

Workaround NotFound using Microsoft Graph API?

If someone doesn't have a profile picture, a NotFound exception kicks me out of the code. How can I work around this?
My Method:
if(graphManager.Client.Users[user.Id].Photo.Content.Request().GetAsync().IsNull())
{
Debug.Log("profilepicture not found");
}
else
{
var photo = await graphManager.Client.Users[mitarbeiter.Id].Photo.Content.Request().GetAsync();`
}
Response: It skips the if cause it thinks it's not null
What I need is a Method to create a Debug.Log if the exception happens and not throw me out
It seems that getting an exception when a photo is not found is a valid case. See docs on errors.
Try to handle it in the following way:
try
{
Stream photoContent = await graphManager.Client.Users[user.Id].Photo.Content.Request().GetAsync();
}
catch (ServiceException ex) when (ex.IsMatch(GraphErrorCode.ItemNotFound.ToString()))
{
Debug.Log("profilepicture not found");
}
P.S. I'm not sure precisely which GraphErrorCode should be used here.
I don't know the library you are using but is it possible that in the moment you do
graphManager.Client.Users[user.Id].Photo.Content.Request().GetAsync().IsNull()
what happens is you are basically doing
var asyncResult = graphManager.Client.Users[user.Id].Photo.Content.Request().GetAsync();
if(asyncResult.IsNull())
which of course would be true since you didn't give it any time to actually perform the request and finish.
It should probably rather be
var photo = await graphManager.Client.Users[mitarbeiter.Id].Photo.Content.Request().GetAsync();
if(photo.IsNull() )
{
Debug.Log("profilepicture not found");
}
else
{
...
}

How to handle specific HttpClient errors

When the HttpClient throws an exception trying to get a page it returns a HttpRequestException. This exception doesn't really have anything to categorize the error apart from the message so the only way i can see to handle errors is like so:
try
{
HttpResponseMessage response = await client.GetAsync("http://www.example.com/");
// ...
}
catch (HttpRequestException e)
{
if(e.Message == "Name or service not known")
{
HandleNotKnown();
return;
}
if(e.Message == "Some other specific message")
{
HandleOtherError();
return;
}
// ... etc
}
I don't like doing this because I feel like at some point the error text could change in an update and break my code.
Is there a better way to handle specific errors with HttpClient?
The HttpRequestException inherits from Exception and so it has the InnerException property
Gets the Exception instance that caused the current exception.
So check this Exception for more details.

How to fix "cannot convert from 'bool' to 'string'" error?

i'm trying to mod an existing discord bot, and i'm getting this error when i try to run it. I'm trying to make one exception when it verifies if the message was sent from a bot or not.
private async Task MessageReceivedHandler(SocketMessage msg)
{
try
{
if (msg.Author.IsBot || !_bot.Ready.Task.IsCompleted) //no bots, wait until bot connected and initialized
throw new ArgumentNullException(msg.Author.Id == 1234)
return;
if (!(msg is SocketUserMessage usrMsg))
return;
#if !GLOBAL_NADEKO
// track how many messagges each user is sending
UserMessagesSent.AddOrUpdate(usrMsg.Author.Id, 1, (key, old) => ++old);
#endif
var channel = msg.Channel as ISocketMessageChannel;
var guild = (msg.Channel as SocketTextChannel)?.Guild;
await TryRunCommand(guild, channel, usrMsg).ConfigureAwait(false);
}
catch (Exception ex)
{
_log.Warn("Error in CommandHandler");
_log.Warn(ex);
if (ex.InnerException != null)
{
_log.Warn("Inner Exception of the error in CommandHandler");
_log.Warn(ex.InnerException);
}
}
}```
You have a couple issues.
First:
throw new ArgumentNullException(msg.Author.Id == 1234)
The constructor for ArgumentNullException takes a string that is supposed to be "The name of the parameter that caused the exception". You are giving it a bool.
But you only have one argument, and by this line you already know it's not null. So maybe just ArgumentException is more appropriate, and write a sentence that describes why the argument is not acceptable.
Second, I don't think this does what you think it does:
if (msg.Author.IsBot || !_bot.Ready.Task.IsCompleted) //no bots, wait until bot connected and initialized
throw new ArgumentNullException(msg.Author.Id == 1234)
return;
If an if statement is not followed by { }, then only the one next line is considered part of the conditional code. (this is true of for, foreach, etc. - read more about "embedded statements" here)
In other words, this is the equivalent to what you have:
if (msg.Author.IsBot || !_bot.Ready.Task.IsCompleted) {
throw new ArgumentNullException(msg.Author.Id == 1234)
}
return;
It will either throw an exception, or return. All the code after the return will never be reached. I don't think that's what you want.
This is one reason I always use braces around single-line code blocks.

Check if element exists appium C#

I have made a number of unit tests and I'm running them using appium. When an error pops up I try and capture it by
if (PowerPointSession.FindElementByAccessibilityId("CreateErrorIcon").Displayed == true)
{
exception = "An error occured when creating Agenda/TOC";
ExceptionHandler(exception);
}
This works fine if I have an error and it finds an element called CreateErrorIcon. However if no error pops up it seems to get stuck at the beginning of the if statement as if it is checking for an element called CreateErrorIconto be displayed and for some reason it never gets out of the if statement if it doesn't find the element.
Has anyone got any ideas or can point me in the right direction on why this is happening?
This post answers your question.
Basically, FindElementByAccessibilityId waits until an element is found or a timeout occurs.
In C# the check would look something like:
private static bool IsElementPresent(WindowsDriver<AppiumWebElement> driver, Action findAction)
{
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.Zero);
try
{
findAction();
return true;
}
catch (Exception)
{
return false;
}
finally
{
driver.Manage().Timeouts().ImplicitlyWait(GuiTestRunner.Timeout);
}
}
and usage:
var isError = IsElementPresent(PowerPointSession,
() => PowerPointSession.FindElementByAccessibilityId("CreateErrorIcon"));
if (isError)
{
exception = "An error occured when creating Agenda/TOC";
ExceptionHandler(exception);
}

DescribeTable Error Type, Amazon DynamoDB

I am referencing this answer to another, very similar question (the only difference being the use of PHP).
I have seen an example of getting detailed error information from an exception throw by AWS DynamoDB's DescribeTable method in PHP (see above linked answer); however, I have had trouble finding similar information in C#.
Here is what I have mimicked so far:
var describeTableResponse = _client.DescribeTable(tableName);
var responseStatusCode = describeTableResponse.HttpStatusCode;
if (responseStatusCode == HttpStatusCode.OK)
{
return true;
}
else if(responseStatusCode == HttpStatusCode.BadRequest)
{
var error = // get detailed information; looking for ResourceNotFoundException
}
throw new AmazonDynamoDBException("Error performing the DescribeTable operation");
Above, client is a correctly configured DB client of type AmazonDynamoDBClient.
Any thoughts on how to do the equivalent of:
$error_type = $response->body->__type;
$error_code = explode('#', $error_type)[1];
if($error_code == 'ResourceNotFoundException')
{
echo "Table ".$table_name." exists.";
}
I actually ended up going a completely different route due to the specification surrounding the .Net DescribeTable() function -- it throws the ResourceNotFoundException.
try
{
_client.DescribeTable(tableName);
}
catch (AmazonServiceException amazonServiceException)
{
if (amazonServiceException.GetType() != typeof(ResourceNotFoundException))
{
throw;
}
return false;
}
return true;

Categories

Resources