So I'm using Next JS API routes and in one of such routes I'm calling a GraphQL mutation using Apollo, something like:
// pages/api/foo.js
import { initializeApollo } from '~/server/apollo'
export default function handler(req, res) {
const client = initializeApollo()
try {
await client.mutate({ mutation: FooDocument })
// this works
res.status(200).send({ foo: '...' })
} catch {
// this fails
res.status(500).send({ error: '...' })
}
}
as you can see if the mutation fails I get a server error when calling res.status(500).send({ error: '...' })
:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
But If the mutation succeeds I got no error when calling res.status(200).send({ foo: '...' })
.
Does anyone knows why this happens? I guess that my best alternative is to call this mutation only in the frontend but I would like to know if there's a way around this.
Oh I see, I had a redirect in the errorLink
of the ApolloClient
configuration, it was hard to spot because this code was in a different file:
const errorLink = onError(({ graphQLErrors }) => {
graphQLErrors.forEach(error => {
if (err.message === 'foo') {
// this redirect was the problem
ctx.res.writeHead(307, { Location: '/somewhere' })
}
})
})
and so the errorLink
was catching the error I was checking out and it was trying to do a redirect, that redirect was setting the headers and it was being ignored since I'm using the API routes. To solve this I just did an early return for that specific operation:
const errorLink = onError(({ graphQLErrors, operation }) => {
if (operation.operationName === 'MyMutation') {
return
}
graphQLErrors.forEach(/*...*/);
})