Possible unhandled promise rejection warning with useMutation - react-apollo

I'm getting an unhandled promise rejection error when I use useMutation with react native. Here's the code producing the issue:
const [createUser, { error, loading }] = useMutation(CREATE_USER_MUTATION);
Anytime my graphql server returns an error to the client I get an unhandled promise rejection error (screenshot below). I'm able to make it go away by adding an error handler like so, but it seems like a hack. Any thoughts? Am I doing something wrong or is this something that should be addressed by the apollo folks?
const [createUser, { error, loading }] = useMutation(CREATE_USER_MUTATION, {
onError: () => {}
});

Your createUser mutation is a promise you should handle error inside try catch block, or in upper scope inside apollo-link-error onError method.

const [createUser, { data, loading }] = useMutation(CREATE_USER_MUTATION, {
onError: (err) => {
setError(err);
}
});
With this we can access data with loading and proper error handling.

Related

handle http errors in rxjs lastValueFrom

I have started to use the lastValueFrom() to handle my observable http requests. One of these http calls is returning an error from the server-side, and I am getting the name: 'EmptyError', message: 'no elements in sequence' message
const response = await lastValueFrom(
this.service.doStuff()
).catch((e) => {
console.log('#1', e);
return {} as DoStuffResponse;
});
at #1 the error is EmptyError , not the error from the http call.
I understand why I am getting it (the http observable does not return a value)
However, what I'd like to know is what the actual error is (a 422 unprocessable entity in this case)
Is this possible ?
I have not found a method to catch the Http errors from lastValueFrom and this does not appear to be documented in rxjs.
As a result I've decided to avoid lastValueFrom when doing Http requests. Instead I stick with Subscribe and always get the Http response codes in the error.
As an aside, many people noticed Subscribe as being deprecated in VSCode, but this is not true; just a certain overload. I know you didn't mention the deprecation as a motivator for using lastValueFrom, but I think most people, including myself, used the VSCode deprecation alert as a prompt to switch.
That said, this Subscribe syntax is still valid and should give you the Http error code:
this.someService.getResults.subscribe(
{
next: (results) => {
console.log('Here are the results...', results);
},
error: (err: any) => {
console.log('Here is the error...', err.status);
},
complete: () => { }
});

Can Sentry catch network error (XHR or fetch) in browser?

I am currently integrating Sentry into an Angular web application.
I am successfully reporting console.log / warn / error and exceptions in Sentry as "issue".
However, when a request to my server fails (HTTP 4XX or 5XX), Sentry totally ignores this error and does not send it.
I have tried all possible values for tracingOrigins.
Sentry.init({
dsn: '******',
integrations: [
new CaptureConsole(),
new Integrations.BrowserTracing({
tracingOrigins: ['localhost', 'http://localhost:4646/api']
})
],
tracesSampleRate: 1.0,
debug: true
});
What can I do ?
You can use the unhandled rejection event found here: https://developer.mozilla.org/en-US/docs/Web/API/Window/unhandledrejection_event
When your promises fail and error out, but are uncaught, this event will fire. Here you can add Sentry.captureException.
However the fact that you have CaptureConsole means you are likely sending all console errors as sentry events, and uncaught 4xx and 5xx should be sent. I assume you are catching and handling these then?
One way to handle these is add Sentry.captureException in your fetch/xhr library when it processes the response object.
If its easier to just log every uncaught error, you can patch the Promise object:
window.Promise = class extends Promise {
catch(func, ...args) {
let loggingFunc = (error = {}, ...args) => {
console.warn('Promise caught', error);
Sentry.breadcrumb('Promise caught', error.message, Sentry.Severity.Error);
return func(error, ...args);
};
return super.catch(loggingFunc, ...args);
}
};
I think you'd want an instance of Sentry running on your server to capture backend errors. You'd probably want to set these up in Sentry as two different projects.
Alternatively, you could manually track them in your Angular app when you get the response back - something like Sentry.captureException(err);

What happens to unhandled async errors in AWS Lambda?

I'm trying to debug a problem that I think is being caused by an uncaught error in an async process. This is simple example that simulates the type of error I'm trying to detect:
async function test(event, context) {
console.log('I can find this log message');
context.callbackWaitsForEmptyEventLoop = false;
setTimeout(() => {
console.log('I cannot find this one');
throw new Error('uh oh'); // I don't see this in CloudWatch, either
}, 1000);
return {};
}
I know the lambda is frozen after the function returns, so I'm guessing there's no way to see these errors/logs.
Is there anything I can do to try to detect what is still in the event loop when the handler returns so I might be able to track down an unhandled error like this one?
You can use subscribe to the unhandled rejections.
process.on('unhandledRejection', error => { // log error});
hope this helps.

Apollo Client on React - How to retrieve the error message fomated?

I can't find info about it in anywhere...
Consider this very simple scenario...
<Mutation mutation={LOGIN_MUTATION}>
{(login, { data, loading, error }) => {
if (error) {
console.log(error)
}
I am receiving a string error message like...
Error: GraphQL error: ERROR_INVALID_LOGIN_PROVIDER
at new ApolloError (bundle.umd.js:92)
at MutationData.onMutationCompleted (react-hooks.cjs.js:636)
at react-hooks.cjs.js:559
at tryCallOne (core.js:37)
at core.js:123
at JSTimers.js:289
at _callTimer (JSTimers.js:146)
at _callImmediatesPass (JSTimers.js:194)
at Object.callImmediates (JSTimers.js:458)
at MessageQueue.__callImmediates (MessageQueue.js:366)
I can't take actions based on the error message formated in this way. ERROR_INVALID_LOGIN_PROVIDER could be ERROR_INVALID_PASSWORD, for example...
I need to take decisions based on the error messages. but I just receive a string containing the graphql error, the modules inside the js and a lot of information that's not important. Is there any way to receive the error message formatted imn a way that I can extract only the server error ?
This should be possible
error in your example should be an ApolloError with the possible GraphQLErrors or a NetworkError
(login, { data, loading, error }) => {
if (error) {
if (error.graphQlErrors && error.graphQLErrors.length > 0) {
// There are graphQL errors and there may be multiple but its always an array.
// You should handle it properly
const { message } = error.graphQLErrors[0]
console.log(message) // e.g. ERROR_INVALID_LOGIN_PROVIDER
} else if (error.networkError) {
// There may be a network error
const { message } = error.networkError
console.log(message) // e.g. NetworkError when attempting to fetch resource.
}
}

Error handling using the catch block in cypress

I'm trying to handle an error in Cypress but the Cypress app is throwing error
cy.get('button[name="continue"]',{timeout: 30000})
.catch((err) => {
cy.console.log("error caught");
})
The error I get:
TypeError: cy.get(...).catch is not a function
tl;dr
Cypress has no .catch command the error message clearly states that.
Exception handling in Cypress
The documentation on error recovery clearly states:
The following code is not valid, you cannot add error handling to Cypress commands. The code is just for demonstration purposes.
cy.get('button').contains('hello')
.catch((err) => {
// oh no the button wasn't found
// (or something else failed)
cy.get('somethingElse').click()
})
They deliberately left this out and in the docs they explain it in great length why you shouldn't be able to do it.
If you really want, you can catch uncaught exceptions, just try the suggestions of the Catalog of Events on this matter:
it('is doing something very important', function (done) {
// this event will automatically be unbound when this
// test ends because it's attached to 'cy'
cy.on('uncaught:exception', (err, runnable) => {
expect(err.message).to.include('something about the error')
// using mocha's async done callback to finish
// this test so we prove that an uncaught exception
// was thrown
done()
// return false to prevent the error from
// failing this test
return false
})
// assume this causes an error
cy.get('button').click()
})

Resources