Catch all errors on React 15.3.1 - javascript

I need catch all javascript error that happen on client browser to send to Rollbar. I tried a lot of solutions like window.addEventListener and overwrite console.error method but none of the worked for me.
Ajax errors I already get, like the jqXHR on image, but it have less information on must time.
But the message above (in red) I cannot.
How to really get all browser erros messages with React?

I don't think the error you're seeing has anything to do with React, it's thrown by your browser because your script is trying to make a cross domain request.
Have a look at this for more details:
How does Access-Control-Allow-Origin header work?

I think it's not really possible to catch all browser errors in the one place, and it is not a problem of React.
For example, if you want to catch all API errors, the basic technique is to wrap all your API calls to simple function like:
/**
* #returns Promise
*/
export default function httpRequest(type, path, params, headers) {
return someHttpLibrary.request(type, path, params, headers)
catch((error) => {
logTheStuff(error);
});
}
And you should call that function instead of directly requests. Also, the additional achieves of that technique, that you'll be able to log all requests and change library in one place if you'll need it ;D
About other errors, for example errors in Rendering or logic errors, Sentry team wrote nice article about handling errors:
https://blog.getsentry.com/2016/01/04/client-javascript-reporting-window-onerror.html
And also, Sentry is very nice tool to handle React errors: https://getsentry.com/for/react/

Related

Google Firebase httpsCallable raising net::ERR_NAME_NOT_RESOLVED

I am running into net::ERR_NAME_NOT_RESOLVED when calling the API of my firebase project. I have tried using multiple devices, two internet connections, a VPN, Linux, macOS, Windows 11 to rule out any errors caused by my devices. When navigating to the API link on my browser it does not timeout, and I am provided with a response. The issue seems to be when using the httpsCallable function provided by Firebase. No logs of the function being called are present on firebase outside of navigating to it in a browser.
Here is my code:
const functions = firebase.functions
console.log(functions)
const loginWithCode = httpsCallable(functions, 'loginWithCode')
loginWithCode(loginPayload)
.then((result) => {
console.log(result)
})
.catch((error) => {
console.log("ERROR CAUGHT HERE")
console.log(error)
});
The output from my browser console:
service.ts:206 POST https://us-central1-%22crowd-pleaser-75fd7%22%2C.cloudfunctions.net/loginWithCode net::ERR_NAME_NOT_RESOLVED
App.tsx:79 ERROR CAUGHT HERE
App.tsx:80 FirebaseError: internal
The result from directly inputting the link on the firebase web interface:
{"error":{"message":"Bad Request","status":"INVALID_ARGUMENT"}}
Is there something I am missing that is creating this issue? I have scoured the internet, and StackOverflow looking for an answer, and all solutions provided have not worked. The method implemented is exactly how it is done on the Firebase docs here
Edit: It seems like the link to which my post request is being sent is formatted oddly. Maybe this could be the issue? I can't figure out why it's formatted this way though.
I found a solution to the problem. My speculation in my edit was correct, the URL to which the post request was being sent by httpsCallable was formatted incorrectly. I am unsure as to why it was being formatted this way, however, the quick solution is to set the customDomain class attribute of the object returned by getFunctions to the correct domain. In my case this was done by doing:
functions.customDomain = functions.customDomain = 'https://us-central1-crowd-pleaser-75fd7.cloudfunctions.net'
The variable 'functions' in the code above is the class attribute returned from the method getFunctions provided by Firebase
The Thing
While I'm not an expert on Firebase the problem is that you're making a wrong HTTP request with loginWithCode(loginPayload), there is nothing wrong with your code that I can see at least.
By the way, you're using:
const loginWithCode = httpsCallable(functions, 'loginWithCode')
rather than a simple const loginWithCode = httpsCallable('addMessage')
as described here: Google FireBase Docs
And then, making a loginWithCode({ text: messageText })
Also, as you can see here: Google Firebase Docs:firebase.functions.HttpsCallable
You will be able to pass any type of data to the HttpsCallable function, so we end at the start point: you're making a wrong HTTP request.
As described in the HTTP answer the error is: net::ERR_NAME_NOT_RESOLVED this happens when a DNS request cannot be resolved, then a domain doesn't exists so this all leads to the thing that there is no way to send the HTTP request since there is not a route in the internet that was found to send it.
The Problem:
While decoding the url that you're making the HTTP request
service.ts:206 POST https://us-central1-%22crowd-pleaser-75fd7%22%2C.cloudfunctions.net/loginWithCode net::ERR_NAME_NOT_RESOLVED
App.tsx:79 ERROR CAUGHT HERE
App.tsx:80 FirebaseError: internal
You will find that you're sending the HTTP request to:
https://us-central1-"crowd-pleaser-75fd7",.cloudfunctions.net/loginWithCode
As you can see, you will find that when making the HTTP request it will be a problem: since you cannot put "crowd-pleaser-75fd7", in the URL to make the HTTP request. That is generating the error net::ERR_NAME_NOT_RESOLVED
I'm not sure what exactly are you trying to do, but I think that the correct URL to the HTTP request should be:
https://us-central1-crowd-pleaser-75fd7.cloudfunctions.net/loginWithCode
With this URL the HTTP request must pass, at least. And I suggest then check the loginPayload in order to fix this.

How to reliably distinguish fetch api rejects?

Is there a clearly defined guide on how to check on what a fetch call might reject with?
I'm developing an application similar to Postman (or any other api explorer), but without the electron shell, which means I have to rely on what's available in the browser. I would like to clearly distinguish what exactly went wrong when fetch rejects.
But browsers seem to reject with completely different messages, for even the most basic stuff. Relying on the error being an Error or TypeError is not very useful in itself.
For example with my currently installed browsers fetching a non existing endpoint will result in
Chrome - TypeError: Failed to fetch
Firefox - TypeError: NetworkError when attempting to fetch resource.
Safari - TypeError: Type error
Without knowing what other error types there might be, it's duck typing on a whole new level.
So my question is: how exactly could errors be reliably distinguished? Is there any library that "standardizes" errors?
I need to be able to tell the user, that "Your endpoint doesn't exists or the network is down" or "You provided wrong headers, which are wrong for this and that reason".
Update
To be clear, with a code example:
fetch('...some url...', { /* some args */ })
.then((response) => {
// I'm good here, it's clearly documented
})
.catch((error) => {
// How do I figure out what EXACTLY went wrong here?
})

Handeling Node, Express background errors

I am quite unsure how I should properly handle uncaught exceptions that occurs in my node.js/express app. Right now I have an Express app that will send all caught errors to an Express error handeler using next(err):
function(err, req, res, next) {
// Do something with the error
}
This seems to work all fine and well for errors I have anticipated. For instance a database connection not working, essentially all things that will return a callback(err). Thought problem occurs when I want to preform a background task, which will finish after the response has been sent. For instance:
app.get('/url', function(req, res) {
BackgroundTask.run() // Here an uncaught exception occurs, for instance a bug
res.send('Running your background task')
}
The background modules that I want to run aren't express related (no use of req,res) and upon a caught errors they will use a custom in errorHandeler that will send the error to some error reporting service. However when an uncaught exception occurs in one of these background tasks I have no clue how to send the error to my error report service (Raygun in this case). The only thing that seems to work is to add a process.on('uncaughtException') event listener. However almost every post on the subject describes the latter a 'bad' or crude way of doing things. They seems to recommand using node domains however I don't really see how I can implement these for background tasks.
I use process.on(uncaughtException), because all you're really trying to do is catch the output from the error and shut the server down gracefully (and then restart). I don't see any reason to do anything more complicated than that, because by nature of the exception, you don't want your application doing anything else in that state other than shutting down.
Domains are an alternative way of dealing with this, but it's not necessarily better than using the process handler, because you're effectively writing custom logic to handle things that you aren't anticipating. It does give you finer granularity in terms of what your error handler does for different error types, but ultimately you're still potentially running your application in an unknown state after handling it. I'd rather have my application log the exception, shut down, and then i'll fix the error so it never happens again, rather than risking my user's data on a domain solution which may or may not have handled the error correctly, depending on the nuance of the error it encountered.

How to hide error message in angularjs http request?

I have get a request from an API, some times I would get the EXIF information, but sometimes I will get error message {"error":"no exif data"} How can I hide this error message.
In chrome, the error is 400 (Bad Request)
$http.get(res.getQNUrl(domain, key, "exif"))
.success(function(data){
$scope.imageExifMap[key] = data
}).error(function(data,status,headers,config){})
The error message you mentioned above is browser specific. It is a browser logging functionality.
Well there is a workaround(not a solution since its not a problem) for it. I would not recommend it since its a built-in browser functionality you are trying to suppress from doing the task it is meant to do, but if that is what you want then here are couple of ways to achieve it.
Using a regular expression filter like so
^(?!.* 404 \(Not Found\))(?!.*[file name])
Using a Log filter like so
I have not explained it much because there is already an SO question that explains these in detail.
Please refer this SO for detailed explanation regarding the above mentioned workarounds.

Backbone JS - Deleting a model in a REST interface

I am writing a Backbone application which should interface to a REST API.
My problem arises when a user deletes a model that has already been deleted by someone else. In my opinion, the backend should just return success (200), as the model is deleted anyway. But the people developing the server side have a different opinion, hence what I get is a 404. For comparison, when the request actually fails - hence the model is still alive - the response code is 400, or possibly 401 for authorization issues.
Since I get an error, I actually do not remove the model. What I am trying to do is modifying this behaviour: if I get a 404 error while deleting a model, it should be treated as success. But I am not really sure what is the most convenient way to handle this.
Ideally I would like to avoid putting this logic inside model.destroy. This would lead to a repetition. I could put this inside a destroy method of a superclass, but models override this method anyway, each one with its own logic, so it gets messy. I would prefer that at this point the model.destroy methods received a success, not knowing that the actual response was a 404.
On the other hand, I am not sure how to put this logic inside Backbone.sync, short of rewriting the whole function.
What is the most transparent way to transform all 404 responses to DELETE requests into success?
It's a hack, but should do the trick:
model.destroy({
error: function(model, resp, options) {
if (resp.status == 404) {
resp.status = 200;
options.success(model, resp);
}
}
})
Btw, as of Backbone 0.9, destroy() and create() are optimistic.

Categories