I want to catch a firestore error and execute code based on what kind of error it is. (My database is build that if a document doesn't exist you won't be able to access it and therefore I have been getting a lot of permission-denied errors for non-existent documents. My solution is to check the error and create a document if I get a permission denied error.)
This is my current code:
userDataDocRef.collection('emailPreferences').doc('main').get().then(function(doc) {
if (doc.exists) {
var data = doc.data();
console.log(data);
var getGameUpdates = data.getGameUpdates;
switchEmailNewGames.checked = getGameUpdates;
} else {
}
}).catch(function(error) {
console.log(error)
if (error == firebase.firestore.FirestoreError.permission-denied) {
console.log('FIREBASE PERMISSION DENIED ERROR')
}
})
My Question: How do I check what kind of error I got properly? (what I have at the moment doesn't work)
Thank you for your help!
There is no way to determine from the response what specific security rule failed. This is by design, since exposing this information would give malicious users access to important information about how your database is secured. That's why the error message sent to the client is always a generic "permission denied".
In general depending on error message like this for regular flow control sounds like an antipattern. If you only want to create a document if it doesn't exist, perform the check in a transaction, which ensures the check and create happen atomically.
Related
We are trying to setup error handling on a SignalR Core invoke method from a JavaScript client that needs to identify the error's type and act accordingly (e.g. if it is an authorization error, the user should be prompted to log in, etc.).
We've determined that the error returned from the hub contains a message and a stack property and have build the following that sets an error code based on the text contained in the message property:
Will the error text always be returned in English (and can thus be used to identify the error)? Or is there a better way to go about achieving this?
We are using .Net Core 3.1 and #microsoft/signalr 3.1.10.
According to aspnetcore/SignalR server-side code on GitHub, it seems that the invocation errors are indeed passed by string value.
The method responsible for send back error are defined as follow:
private async Task SendInvocationError(string invocationId, HubConnectionContext connection, string errorMessage)
{
if (string.IsNullOrEmpty(invocationId))
{
return;
}
await connection.WriteAsync(CompletionMessage.WithError(invocationId, errorMessage));
}
And a few examples on how it is being called:
if (!await IsHubMethodAuthorized(scope.ServiceProvider, connection, descriptor, hubMethodInvocationMessage.Arguments, hub))
{
Log.HubMethodNotAuthorized(_logger, hubMethodInvocationMessage.Target);
await SendInvocationError(hubMethodInvocationMessage.InvocationId, connection,
$"Failed to invoke '{hubMethodInvocationMessage.Target}' because user is unauthorized");
return;
}
var errorMessage = ErrorMessageHelper.BuildErrorMessage($"Failed to invoke '{bindingFailureMessage.Target}' due to an error on the server.",
bindingFailureMessage.BindingFailure.SourceException, _enableDetailedErrors);
return SendInvocationError(bindingFailureMessage.InvocationId, connection, errorMessage);
The only information about error is the string parameter of errorMessage.
On the other hand, the client-side javascript library source code:
HubConnection.prototype.connectionClosed = function (error) {
this.logger.log(_ILogger__WEBPACK_IMPORTED_MODULE_2__["LogLevel"].Debug, "HubConnection.connectionClosed(" + error + ") called while in state " + this.connectionState + ".");
// Triggering this.handshakeRejecter is insufficient because it could already be resolved without the continuation having run yet.
this.stopDuringStartError = this.stopDuringStartError || error || new Error("The underlying connection was closed before the hub handshake could complete.");
// If the handshake is in progress, start will be waiting for the handshake promise, so we complete it.
// If it has already completed, this should just noop.
if (this.handshakeResolver) {
this.handshakeResolver();
}
this.cancelCallbacksWithError(error || new Error("Invocation canceled due to the underlying connection being closed."));
...
};
This indicates that "Invocation canceled due to the underlying connection being closed." is the default error message when none was provided by server.
Therefore, I believe if the SignalR team didn't change the error message sending mechanism, your string.includes approach is reasonable.
When using an api I often find myself with a rather complicated error object.
Depending on the API that I am using the error texts are quite helpful and I would actually sometimes like to display them directly to the user. The problem, of course, is that the error objects can look quite differently so it would be very verbose to go through them and pick individual objects in case they exists (dependant on the status code of the error).
Is this just the nature of the error object or is there a better way to do this?
What I do to handle API calls that end up with error is this:
try {
const response = await axios.post("Your URL");
// Your code to handle the result
} catch (error) {
console.log(error.response.data.error)
// Code to display the error to the user
}
error.response.data.error is the actual error message sent from the server, not the error code
everyone!
I got a problem: I'm trying to validate registration form. Totally, it works ok, but I need to validate form via server. In my case, for example, I need to figure out if email is already taken.
I tried to fetch and async/await syntax, but problem is still the same:
DOMException: "The operation was aborted. "
The way I understand it right now is readableStream (what actual response body is) is locked. So the wrong error is thrown, and I cannot get server response.
try {
const response = await fetch(options.url, options.requestOptions);
const body = await response.json();
if (options.modifyDataCallback instanceof Function) {
body.data = options.modifyDataCallback(body.data);
}
return body.data;
} catch (error) {
throw error;
}
How do I see the solution? I send request and recieve some server error like
code: email_in_use
message: Email '...' is already in use.
Then I need to throw error and catch it in other place in order to show corresponding error message to client.
In browsers network tab I do receive what I want to receive, but can't get the same JSON-response in my code.
Google chrome provided more information: net::ERR_HTTP2_PROTOCOL_ERROR 200.
And the problem was on backend. It is written in C# and API method returned Task. The problem was solved by adding async/await for this method.
How do I listen to an uncaught exception error in meteor?
The errors are of course specific to the cause, so please can you provide a pseudo style code/explanation that states the concept of handling this error.
An example use case:
A user clicks 'logout' but there is an uncaught exception and the user does not get logged out and so the connection to the server remains open.
You can use the callbacks, they usually provide a reason parameter. E.g
Meteor.call("some_random_non_existent_method", function(err, result) {
if(err) return alert(err.reason)
});
Most meteor callbacks have a error param. With the logout its Meteor.logout(function(err) { ... })
You should be able to catch most types of errors like this. If you want to capture all errors you can use try..catch. Everything in the try block will try to run until it throws an error. You can catch this and provide feedback to the user.
try {
//This will throw an error
this.run_something.go_make_error()
}catch(e) {
alert("There was an error running this");
}
I've been reading the firebase documentation and it is very much asynchronous code that is used. I wanted to know if firebase is throwing errors and/or passing error data in the callbacks. As far as I can tell, the documentation makes no mention of it.
Thanks in advance for advice
Firebase doesn't produce developer-consumable errors at the moment (outside exceptions that are thrown for bad inputs). Currently Firebase operations are guaranteed to either succeed or never trigger events. In the case of network connectivity issues, Firebase will simply not trigger events. This is expected behaviour, as Firebase is designed to work in offline mode, and it will automatically bring you up to speed once a connection has been re-established.
Note that in the future we will throw errors for security violations and possibly other error types. The API for catching and handling these errors has not been written yet.
You need to create a auth function that handles the errors. See the jsFiddle below for a great example.
function initAuth(ref) {
return new FirebaseSimpleLogin(ref, function (err, user) {
// if there is an error then display it
if (err) {
displayError(err);
} else if (user) {
// we only want to log people in through the email/password provider
if( user.provider !== 'password' ) {
auth.logout();
}
else {
// logged in!
uid = user.uid;
// save the user to our firebase
ref.child(user.uid).set({
id: user.id,
uid: user.uid,
email: user.email
});
// switch over the the user info screen
switchView('userInfo');
}
} else {
// logged out!
console.log('not logged in');
}
});
}
http://jsfiddle.net/firebase/wPBj5/embedded/result,js/