Here is my client configuration using Apollo Boost :
new ApolloClient({
uri: `${window.location.origin}/api`,
cache: new InMemoryCache(),
onError({ graphQLErrors, networkError }) {
if(graphQLErrors)
graphQLErrors.forEach(error => notification.error({
message: 'Error',
description: error.message
}))
if(networkError)
notification.error({
message: 'Network Error',
description: `A network error has occurred. Please check out your connection.`
})
},
request(operation) {
const currentUser = readStore('currentUser')
currentUser && operation.setContext({
headers: { authorization: currentUser.token }
})
}
})
Intended outcome:
Before the bug, the onError callback used to catch errors just fine.
Actual outcome:
Errors are said to remain uncaught and cause apps (using CRA in my case) to crash.
How to reproduce the issue:
Try switching to the latest version of apollo-boost and just throw a Graphql error on the server.
Versions
React : 16.12.0
Apollo-boost : 0.4.7
for me query errors are fine and mutation errors throw uncaught exception, can you confirm if you have the same problem?
for me query errors are fine and mutation errors throw uncaught exception, can you confirm if you have the same problem?
Yep, same for me.
I think I got the same thing as Uncaught (in promise) Error
logged.
But...,finally, I resolved by adding catch
in promise mutation, for example. You have:
const [login] = useMutation(LOGIN)
then when you call mutation by an event
login({
variables: {
input: { email, password }
}
}).catch(err => console.error(err))
Our issue may resolve, but onError
issue is still there, maybe because of promising stream is not correctly, I'm not sure.
I'm having a similar issue. When the response from a mutation contains an error I get an error that there was an unhandled rejection. This slows development since react-dev-server
displays an error overlay that you have to close. Errors from useQuery
and useLazyQuery
are handled differently, they get caught internally by apollo-client
. At the moment I'm doing
const [cb, {data, error}] = useMutation(MUTATION, {onError: () => null})
but that's not ideal either. I was previously using apollo-boost and this was not an issue.
I'm also seeing this issue. Any mutation-generated network error throws unhandled exceptions, while query-generated errors do not. My onError
method is similar to the one above, but I'm not using Apollo Boost. Adding a catch
block to the mutation "fixes" the issue but is a pretty gross solution.
Any word on this from the maintainers? This seems like a pretty big regression.
"apollo-client": "2.6.8"
"apollo-link-error": "1.1.12"
"react": "16.12.0"
also seeing the same problem. @viiiprock thanks for the workaround.
Same issue here.
If I had to guess I'd say this line in the catch block makes the trouble.
MutationData.runMutation
````ts
private runMutation = (
mutationFunctionOptions: MutationFunctionOptions<
TData,
TVariables
= {} as MutationFunctionOptions
) => {
this.onMutationStart();
const mutationId = this.generateNewMutationId();
return this.mutate(mutationFunctionOptions)
.then((response: FetchResult<TData>) => {
this.onMutationCompleted(response, mutationId);
return response;
})
.catch((error: ApolloError) => {
this.onMutationError(error, mutationId);
if (!this.getOptions().onError) throw error; // !!! I mean this line
});
};
// ... more code here...
private onMutationError(error: ApolloError, mutationId: number) {
const { onError } = this.getOptions();
if (this.isMostRecentMutation(mutationId)) {
this.updateResult({
loading: false,
error,
data: undefined,
called: true
});
}
if (onError) {
onError(error);
}
}
````
Of course I don't know the whole implementation but it seems to me that in MutationData.onMutationError the errors are already handled pretty well, onError will be called conditionally as it should be so I'm not sure if rethrowing the error is really necessary.
Any update on this? I have a pretty large app that relied on this pattern to minimize the amount of try/catch and .catch that was needed. Made for a super clean code base knowing I could rely on apollo-link-error when needed.
Not sure what changed, guess I need to look at my past few commits, but lately all mutation errors throw an unhandled error.
Is this change documented in a change log somewhere?
apollo v3.1.3 confirm the same error
Why is there no activity on this issue? It has been around since December 2019, useQuery
and useLazyQuery
work as expected so it seems like a deal-breaker for me. I don't want to write try/catch logic around mutations, that's why I use the hooks so I can respond to changes in the UI without side-effect code.
It's been almost a year. Why does no one solve this problem?
As a workaround, my solution is that since I catch all possible/uncatched errors in the onError
link and I have no need to forward the errors to other links or whatsoever, I use response.errors = undefined
at the end of my error handler. It makes the unhandled errors message goes away.
@noglitchyo Could you please share the onError you have implemented ? I need to get execution terminated at onError in case of a mutation
@krakzk Yep, for sure!
const errorLink = onError(({graphQLErrors, networkError, response}) => {
if (graphQLErrors) {
graphQLErrors.map(({message, extensions, locations, path}) => {
// custom error catching logic
}
response.errors = undefined
}
}
On my end, the "custom error catching logic" do operations depending on extension categories / content of messages, then dispatch an action to my errors reducer. Hope it helps.
@noglitchyo I have a question that is out of the scope of this open issue, but would you by any chance know a way to show a modal inside the onError by which i can alert the user about the error details
hate this lib and react.
bloated and fully opinionated 馃憥
@noglitchyo you have a top catch custom errors, but what about custom actions errors .. you can't keep the logic inside the error link .. c'mon.
I'm try to fix it with response.errors = undefined but it doesn't work in any case. I have to add the onError
in each query or mutation :/
It's a big Apollo's fail. Looks like the library has some problem. It has more than 600 open issues and the roadmap for the V3 is from 2018. I don't know if it will be done. About the onError I "fixed" it with a patch:
type useMutationFnType<TQuery, TVariables> = (
baseOptions?: MutationHookOptions<TQuery, TVariables>
) => MutationTuple<TQuery, TVariables>;
function useWithErrorMiddleware<TQuery, TVariables>(
useMutationFn: useMutationFnType<TQuery, TVariables>,
baseOptions?: MutationHookOptions<TQuery, TVariables>,
) {
const onError = (error: ApolloError) => {
if (baseOptions && baseOptions.onError) {
baseOptions.onError(error);
}
return false;
};
const options = {
...baseOptions,
onError,
};
return useMutationFn(options);
}
So you can use it like. I'm using codegen:
const [updatePasword, { loading, error }] = useWithErrorMiddleware(
useProfileUpdatePasswordMutation,
{
errorPolicy: 'all',
onCompleted: (data) => {
if (data) {
const { message, type } = data.profileUpdatePassword.message;
notification[type]({ message });
}
},
},
);
Found a workaround that worked for me in an old issue comment.
With apollo-link-error return Observable.of(operation);
at the end of the error handling logic.
import { onError } from "apollo-link-error";
const errorLink = onError(({ graphQLErrors, networkError, operation, forward }) => {
if (graphQLErrors)
graphQLErrors.forEach(({ message }) =>
console.log(`[GraphQL error]: Message: ${message}`)
return Observable.of(operation);
);
if (networkError) {
console.log(`[Network error]: ${networkError.message}`);
return Observable.of(operation);
}
return forward(operation);
});
I think it's going in the right direction @adisrael , but it's not working for me.
I mean, I see the global log console.log([GraphQL error]...
, but shouldn't it go back also until the mutation? and have result.errors filled?
const result = await CreatePeople({
variables: { fields, accountId: contratId },
});
console.log(`result.errors`, result.errors);
Thx for your help
@jycouet you may have a look over this issue
if you have @client fields
.. they might by the reason of not getting the errors.
nope, I don't have any @client fields
Most helpful comment
Any update on this? I have a pretty large app that relied on this pattern to minimize the amount of try/catch and .catch that was needed. Made for a super clean code base knowing I could rely on apollo-link-error when needed.
Not sure what changed, guess I need to look at my past few commits, but lately all mutation errors throw an unhandled error.
Is this change documented in a change log somewhere?