How to handle Apollo Graphql query error in Vue.JS? - graphql

I am using Vue.js with Vue-Apollo and trying to fetch shared member list using query. I am using the graphQL service in backend.
I am using apollo 'error' function to handle GraphQL error. When the request is made with invalid input, I can see the errors in the network tab, I can see the JSON for the custom errors messages. But I can't console the errors in 'error' function.
Here is the apollo query that is used to fetch shared member list -
apollo: {
sharedMembers: {
query: gql`
query item($uuid: ID) {
item(uuid: $uuid) {
...itemTemplate
members {
...member
permission
}
}
}
${ITEM_TEMPLATE}
${MEMBER}
`,
variables() {
return {
uuid: this.$route.params.uuid,
}
},
update(data) {
return data.item.members
},
error(error) {
console.log('errors', error)
}
},
},
The network response I got -
network_error

Using graphQLErrors
You could get the errors by looking in the error object for graphQLErrors:
error(error) {
console.log('errors', error.graphQLErrors)
}
or
error({ graphQlErrors }) {
console.log('errors', graphQLErrors)
}
Using apollo-error-link
You can use apollo-error-link to help solve your problem if the above doesn't work, docs here.
Here's an example from the docs and I added to it in the networkErrors section to show what you can do to edit the error message you see in your error block, or catch block if its a mutation.
import { onError } from "apollo-link-error";
const link = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors)
graphQLErrors.map(({ message, locations, path }) =>
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
),
);
if (networkError) {
// Add something like this to set the error message to the one from the server response
networkError.message = networkError.result.errors[0].debugMessage
console.log(`[Network error]: ${networkError}`)
};
});
And then in your code:
error(error) {
console.log('error-message', error.message)
}
The console should then log your debugMessage from the server.

unfortunately i couldn't find out how i'd handle errors in such of graphql method call, but as an option you could provide onError method to ApolloClient constructor options. first argument is the error object. hopefully it may help. like so..
const apolloClient = new ApolloClient({
uri: 'http://localhost:4000',
onError(err) {
console.log(err)
},
})

Related

convert data to error in a custom ApolloLink

I'm trying to create a custom ApolloLink that converts specific graphql data to an error which will be passed to the onError link. The omg help! error is successfully passed as a network error to onError, but I also get a run time error in my browser: Uncaught (in promise) Error: omg help! at new ApolloError which should not be happening. How do I make sure the error is entirely handled in onError and not also throwing a runtime error from the TransformErrorLink code?
TransformErrorLink.js:
import { ApolloLink, Observable } from 'apollo-link-core';
class TransformErrorLink extends ApolloLink {
request(operation, forward) {
const observable = forward(operation);
return new Observable((observer) => {
observable.subscribe({
next: (value) => {
// reroute Error types as proper errors
for (const [req, res] of Object.entries(value.data)) {
if (res?.__typename?.includes('Error')) {
observer.error(new Error('omg help!'));
}
}
observer.next(value);
},
error: observer.error.bind(observer),
complete: observer.complete.bind(observer)
});
});
}
}
export default new TransformErrorLink();
the composite set of apollo links:
import { from, HttpLink } from '#apollo/client';
import { onError } from '#apollo/client/link/error';
import transformErrorLink from './transformErrors';
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors)
graphQLErrors.forEach(({ message, locations, path }) =>
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
)
);
if (networkError) console.log(`[Network error]: ${networkError}`);
});
const additiveLink = from([
errorLink,
transformErrorLink,
new HttpLink({ uri: process.env.GRAPH_API_URL })
]);
export default additiveLink;
I tried swapping the order of errorLink and transformErrorLink in the additiveLink, but that resulted in just a runtime error with no console log first.
I have also been reading https://www.apollographql.com/blog/frontend/apollo-link-creating-your-custom-graphql-client-c865be0ce059/ which does the reverse of what I'm doing - convert an error to data.
I haven't used apollo-link-core before, but should you not return observable's projection like in the last line below?
class TransformErrorLink extends ApolloLink {
request(operation, forward) {
const observable = forward(operation);
return new Observable((observer) => {
**return** observable.subscribe({
...
I figured it out - I needed to add an errors property (of type Array) to value and then call observer.next with value instead of calling observer.error with an Error.

error Policy in Apollo Client React does'nt work

I have aproblem when test Apollo.When I try query with apollo and graphql, i want response return error and partical data, so I set property errorPolicy:'all'. But its not work. I don't no why? Help please!
Here my code:
query { animal {
name
age }, school {
name
numberfd } } `
const { loading,data,error} = useQuery(GET_DASHBOARD_DATA, {
errorPolicy:'all',
onCompleted: (res) => {console.log("complete",res)},
onError : (res,data) => {console.log("ERRRR",res,data)},
})
and i want to receive:
{
error:[...], data:[animal:[...]] }
but its only response error.Here is Apollo's doc: https://www.apollographql.com/docs/react/data/error-handling/
onError type is onError?: (error: ApolloError) => void;. You don't have data inside onError callback.
After useQuery you can add:
console.log('data', data)
console.log('error', error)
I faced the same issue with errorPolicy: 'all', I only received the partial result inside onCompleted callback of useQuery, but no errors.
I created an ErrorLink like this:
private createErrorLink = () => {
return new ApolloLink((operation, forward) => {
return forward(operation).map((response) => {
// filter out errors you don't want to display
const errors = filterSomeErrors(response.errors);
if (errors && response?.data) {
response.data.errors = errors;
}
return response;
});
});
};
Now inside my onCompleted callback I get my data as well as errors. You will have to tweak your types a bit, because seems there is no errors field on response.data by default.
Mind that if you use onError from Apollo and return something from the link, it will retry your request containing errors!

aws-amplify [ts] Property 'subscribe' does not exist on type '{}'. [2339]

I'm new to aws amplify. I have setup an app using amplify and I have an API that is returning records using GraphQl. I have created a subscription that is supposed to be triggered when creating a new blog entry. The entries are being created. In the documentation https://aws-amplify.github.io/docs/js/api the code samples suggest that I can use the following to subscribe to a mutation. I keep getting an error stating that error TS2339: Property 'subscribe' does not exist on type '{}'. It's coming from the assignment of client. I'm not sure why its saying this and I was hoping that you would be able to help me with this error.
import { onCreateBlog } from './graphql/subscriptions';
//GraphQl subscription
export const onCreateBlog = `subscription OnCreateBlog {
onCreateBlog {
id
name
posts {
items {
id
title
}
nextToken
}
}
}
`;
//ngInit function with an async method
ngOnInit() {
(async () => {
let client = Amplify.configure(awsmobile); // error from here
let subscription = client.subscribe(graphqlOperation(subscriptions.onCreateBlog)).subscribe({
next: data => {
console.log(data);
},
error: error => {
console.warn(error);
}
});
})();
}

How can I catch RelayObervable Unhandled error when graphql errors are returned?

My backend is returning the following response:
const errorMessage = {
errors: [
{
message: 'User is logged out',
},
],
data: null,
};
return res.status(200).json(errorMessage);
My react-native app using relay is returning the following error:
RelayObservable: Unhandled Error Error:
Relay request for `HomeQuery` failed by the following reasons:
This error shows up when I try to query the backend and it returns the above 'errorMessage' graphql errors array. I have no way of catching this error in my relay network layer BEFORE it throws the redscreen. My Relay Environment looks like this:
const network = new RelayNetworkLayer([
urlMiddleware({
url: () => Promise.resolve(`${config.endpoint}backend`),
headers: async () => authenticateHeaders(fetchHeaders),
}),
retryMiddleware({ fetchTimeout: 1000 }),
next => req => {
if (!req.uploadbles) {
req.Accept = 'application/json';
req['Content-Type'] = 'application/json';
}
return next(req);
},
next => async req => {
const res = await next(req);
if (isLoggedOut(res)) {
// Using react-navigation, route to the login screen
dispatch(routeToLogin())
// I also tried returning `dispatch(routeToLogin())` and `{ data: null, errors: res.payload.errors }` without luck
}
return res;
}
]);
Is there a way I can navigate using dispatch(routeToLogin()) without seeing the redscreen error when graphql errors are returned?
Edit 1
For react-relay-network-modern: You can add the noThrow option like so: new RelayNetworkLayer(middlewares, { noThrow: true });
The noThrow option doesn't exist for react-relay-network-layer (relay classic), is there anything I can do to work around it?
Please try noThrow option:
const network = new RelayNetworkLayer(middlewares, { noThrow: true });

How to use GraphQLError for customize messaging?

I am trying to do customize messaging with GraphQLError.
There are few use cases that I want to handle with GraphQL Error:
when username and password did not match, I want to return customize the message that username and password did not match.
When the user entered an invalid email, I want to return customize the message that entered email is not valid.
And few other use cases.
I created a ValidateError.js File to use GraphQLError handling function:
const { GraphQLError } = require('graphql');
module.exports = class ValidationError extends GraphQLError {
constructor(errors) {
super('The request is invalid');
var err = errors.reduce((result, error) => {
if (Object.prototype.hasOwnProperty.call(result, error.key)) {
result[error.key].push(error.message);
} else {
result[error.key] = [error.message];
}
return result;
}, {});
}
}
Here is the code of my application index file app.js:
app.use('/graphql', graphqlExpress(req => ({
schema,
context: {
user: req.user
},
formatError(err) {
return {
message: err.message,
code: err.originalError && err.originalError.code,
locations: err.locations,
path: err.path
};
}
})));
My question is how can I use this function for grabbing graphQLError
formatError
Thanks in advance.
"apollo-server-express": "^1.3.5"
"graphql": "^0.13.2"
Just throw your error in resolver, formatError function will catch each error thrown in resolver.
Here is my work:
appError.js
class AppError extends Error {
constructor(opts) {
super(opts.msg);
this.code = opts.code;
}
}
exports.AppError = AppError;
throw an custom error in resolver:
throw new AppError({ msg: 'authorization failed', code: 1001 });
catch this error in formatError:
formatError: error => {
const { code, message } = error.originalError;
return { code, message };
},
Other sample:
throw your error in resolver:
const resolvers = {
Query: {
books: () => {
throw new GraphQLError('something bad happened');
}
}
};
catch error in formatError:
graphqlExpress(req => {
return {
schema,
formatError: err => {
console.log('format error');
return err;
}
};
})
Here is the output:
format error
GraphQLError: something bad happened
at books (/Users/ldu020/workspace/apollo-server-express-starter/src/graphql-error/index.js:23:13)
at /Users/ldu020/workspace/apollo-server-express-starter/node_modules/graphql-tools/dist/schemaGenerator.js:518:26
at resolveFieldValueOrError (/Users/ldu020/workspace/apollo-server-express-starter/node_modules/graphql/execution/execute.js:531:18)
at resolveField (/Users/ldu020/workspace/apollo-server-express-starter/node_modules/graphql/execution/execute.js:495:16)
at /Users/ldu020/workspace/apollo-server-express-starter/node_modules/graphql/execution/execute.js:364:18
at Array.reduce (<anonymous>)
at executeFields (/Users/ldu020/workspace/apollo-server-express-starter/node_modules/graphql/execution/execute.js:361:42)
at executeOperation (/Users/ldu020/workspace/apollo-server-express-starter/node_modules/graphql/execution/execute.js:289:122)
at executeImpl (/Users/ldu020/workspace/apollo-server-express-starter/node_modules/graphql/execution/execute.js:154:14)
at Object.execute (/Users/ldu020/workspace/apollo-server-express-starter/node_modules/graphql/execution/execute.js:131:229)
Inside of GraphQLError you should have access to GraphQLErrorExtensions which should allow you to append your custom messages when throwing errors.
This answer was written with knowledge of apollo server throwing custom errors through this extensions option. This may be achievable but more complex. I suggest checking out apollo server error: https://github.com/apollographql/apollo-server/blob/main/packages/apollo-server-errors/src/index.ts
It looks like what you can do is just pass any additional information through the extensions, but you will only be able to set it inside the constructor: new GraphQLError('your error message', null, null, null, null, null, {"message1": [ "custom message1" ], "message2": [ "customer message1", "custom message2" ]})

Resources