I want to send a request to this server via Apollo and get a query :
const client = new ApolloClient({
link: new HttpLink({
uri:'http://mfapat.com/graphql/mfaapp/'}),
cache: new InMemoryCache()
})
const FeedQuery = gql
query{
allFmr{
fmrId,
name,
studio,
bedRm1,
bedRm2,
bedRm3,
bedRm4
}
}
` But I'm facing this error message:
Unhandled (in react-apollo:Apollo(FMRScreen)) Error: Network error: Unexpected token < in JSON at position 1
at new ApolloError (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:109336:32)
at ObservableQuery.currentResult (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:109447:28)
at GraphQL.dataForChild (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:103192:66)
at GraphQL.render (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:103243:37)
....
But I can easily open "http://mfapat.com/graphql/mfaapp/" in my browser and get a query. Does anyone know where the problem is?
Intended outcome:
Actual outcome:
How to reproduce the issue:
Version
hello, this error means your server is sending a HTML file instead of a JSON file as expected. typically this is a result of querying a path that is not found, so the server is sending its catch-all html file (usually a 404)
so its likely your server set up is at fault here, not apollo-client. Please look harder on your server side.
His server is at fault, but this error message shows apollo-client also misbehaving.
If a response comes back with a status code 502, 404, or really anything other than 200, and especially with a content-type indicating the response is HTML, I don't think apollo-client should try to decode it as JSON.
It's not really a big deal, but at the very least the error message produced by querying a missconfigured server could be improved.
any update about this issue? my app always crash when getting 500 response from third party, and I don't know how to handle this
Same here, even though i'm not sure if this belongs here, or in apollo-link-http, or somewhere else in the apollo ecosystem. Whenever my server returns a 401 unauthorized, the client fails miserably because he is trying to json decode the response body, which is the string "Unauthorized".
What's the best practise here?
+1 on better error handling for this case
I think the ability to override the parse step for apollo-link-http would be valuable. It seems brittle to ignore what's in Content-Type and assume that all responses are valid JSON. We should be given the flexibility to handle non-graphql responses if need be.
👍
This seems quite important. There's no way to do this through apollo-link?
That would be quite appreciable, so that the error can be properly handled.
On one hand, that would help show a clean error to the user, and on the other hand, make a proper report to sentry/rollbar services. Basically, giving the error code and the error message as is.
Since this ticket, has there been any strategy to try to handle that? If there is what that would be?
If not, what would be the best strategy to handle this (where and how)… If I get enough time, I might give a try to write a patch ☺
I just got burned by this and it's very confusing ... Here's a blog post that helped me: https://www.jaygould.co.uk/dev/2018/08/11/react-apollo-global-error-handling.html.
However, in general, ApolloClient does a poor job of handling 401s which can be very common if for example a JWT token expires or if an invalid JWT token is sent from client to server (e.g. if the server needs to rotate the signing key as part of security best practices or in response to a breach).
There's only really ApolloClient and ApolloServer involved here and neither seem to do a great job handling this. Any chance for some love from the Apollo team here? :-) @sw-yx
I managed to resolve this issue by using an error handler middleware to always return erros as JSONs, so that Apollo Client error link can parse the errors.
// Error handler
const errorHandler = (err, req, res, next) => {
if (res.headersSent) {
return next(err);
}
const { status } = err;
res.status(status).json(err);
};
app.use(errorHandler);
I followed the advice given here and forced my server to output only JSON error messages. But now, I'm hit with
Error: Network error: Response not successful: Received status code 500
at new ApolloError (ApolloError.js?d4ec:37)
at Object.error (QueryManager.js?96af:212)
at notifySubscription (Observable.js?a7b2:134)
at onNotify (Observable.js?a7b2:165)
at SubscriptionObserver.error (Observable.js?a7b2:224)
at notifySubscription (Observable.js?a7b2:134)
at onNotify (Observable.js?a7b2:165)
at SubscriptionObserver.error (Observable.js?a7b2:224)
at eval (httpLink.js?bfb2:138)
Basically, this library is trying to parse errors on its own instead of passing it to the client. The only way is to set my 500 JSON error responses to respond with a 200 status code..which goes against the best practices and illogical as well...(sending a 200 for a 500?)
How can we instruct this library to stop messing with our errors?
A work around is to provide a fetch handler to Apollo Http Link that will check for errors and return something that Apollo can handle:
const customFetch = (uri, options) => {
return fetch(uri, options)
.then(response => {
if (response.status >= 500) { // or handle 400 errors
return Promise.reject(response.status);
}
return response;
});
};
const client = new ApolloClient({
link: createHttpLink({
uri: "/graphql",
fetch: customFetch,
}),
cache: new InMemoryCache()
});
This seems suboptimal. I would really appreciate better handling.
What I do:
Server:
import {AuthenticationError as AuthError} from "apollo-server-koa";
...
throw new AuthError("Some message")
What I expect:
apollo-client's apollo-link-error link receives AuthenticationError - Some Message
What happens:
apollo-client receives Network error: Unexpected token N in JSON at position 0
I'm having the same error message but my server is fine. I can run the queries in graphql playground without any issues. What else could be causing this? Is there any way to debug it further?
For all those, who are still struggling for the same issue, here's something which might solve it.
First of all, the default ApolloClient function in const client = new ApolloClient(); takes some (optional) parameters.
If you don't specify any parameters and leave it blank, by default it considers host of your front-end client as its graphql uri.
Means it makes request to wrong place. For example, if your front-end app is hosted at localhost:3000, it will make request at localhost:3000/graphql, where your graphqli doesn't exist. Hence, the 404 error.
If you want to reproduce this, then follow this steps: Once error occurs, open dev tools, go to network, find the request throwing 404, in this case you will have to go to "XHR", you will find 404 for your graphql request. Notice the url where its trying to make calls. And, compare that url with where you are running your GraphiQL (your graphql server).
For me, my app was hosted at localhost:3001. And, my GraphiQL at localhost:3000.
In my case, I was getting 404 when app was making request at localhost:3001/graphiql, whereas it should make request at localhost:3000/graphiql, because that's where my server is running.
So, what's the workaround for this?
It's simple. As I said, ApolloClient() function takes some parameters. Your server uri is one of them.
In my case, doing this worked and my app was fetching data without any problem.
const client = new ApolloClient({
uri: "http://localhost:3000/graphql" // or your graphql server uri
});
Figure out uri of your server and specify it in parameter. It should work.
Thanks for reporting this. There hasn't been any activity here in quite some time, so we'll close this issue for now. If this is still a problem (using a modern version of Apollo Client), please let us know. Thanks!
@jbaxleyiii I can confirm this is still an issue in 2.6.3 of apollo-client. It still tries to parse all responses as JSON regardless of the content-type.
It also happened to me. In my case the API is using for multiple platform so changing the API interface is not the case. So better handling on client side would be ideal. Here is my solution for this using apllo-link-error to recorrect the error message.
import { onError } from 'apollo-link-error';
const errorLink = onError(({graphQLErrors, networkError}) => {
if (networkError) {
// Check if error response is JSON
try {
JSON.parse(networkError.bodyText);
} catch (e) {
// If not replace parsing error message with real one
networkError.message = networkError.bodyText;
}
}
});
We're definitely seeing a lot of this as well. Would be good to have a built in way to handle these.
Agree with btff above:
https://github.com/apollographql/apollo-feature-requests/issues/153#issuecomment-419689501
Better to check the response type and only try to parse body as JSON when appropriate.
I had the same problem working with django as back-end, that's because i was sending a POST request without "crsf token". I solved this problem removing 'django.middleware.csrf.CsrfViewMiddleware' from the MIDDLEWARE in the settings.py.
It worked too on mine, but by removing 'django.middleware.csrf.CsrfViewMiddleware' will this affect security of your website by exposing Cross Site Request Forgery protection @moneco-hub
@johnpaul89 , yes, you're righ, but at lest it will allow you continue your development while you (we) find the solution. Please, let me know when you find it.
@johnpaul89, it works for me.
from django.contrib import admin
from graphene_django.views import GraphQLView
from django.views.decorators.csrf import csrf_exempt
from django.urls import path
urlpatterns = [
path('', csrf_exempt(GraphQLView.as_view(graphiql=True))),
path('admin/', admin.site.urls),
]
Hi everyone. I solved this issue using useLazyQuery over useQuery.
My code:
import { ACCESS_LIST } from "./../../graphql/access";
import { useLazyQuery } from "@apollo/react-hooks";
const AccessList = props => {
const [ accesses, setAccesses ] = useState(null);
const [ getAccess ] = useLazyQuery(ACCESS_LIST, {
onCompleted: data => {
setAccesses(data.accessList);
}
});
useEffect(() => {
getAccesses();
}, []);
...
Another way:
With useQuery: using ssr: false
useQuery(ACCESS_COUNT, {
ssr: false,
onCompleted: data => {
setTotalAccesses(data.accessCount);
}
});
Hi guys,
I am using this configuration and graphql is working fine still getting same error :(
const client = new ApolloClient({
uri: "http://localhost:3000/graphql" // or your graphql server uri
});
please, someone, suggest to me how will it resolve it?
I'm having the same error message but my server is fine. I can run the queries in graphql playground without any issues. What else could be causing this? Is there any way to debug it further?
have you found any solution? I am getting the same issue
@riturajratan Check this thread. If you're importing ApolloClient from apollo-boost then not all the options exist on your client and using createHttpLink won't change the uri.
Check your browser's network tab and see if your graphql requests are being made to the uri you're expecting. In my case, I was specifying http://localhost:4001/graphql but the request was being made to http://localhost:3000/graphql. The response that being sent back was an HTML 404 error code and Apollo was trying to parse it as if it were JSON (hence the error). Changing my import statement fixed the issue.
A work around is to provide a fetch handler to Apollo Http Link that will check for errors and return something that Apollo can handle:
const customFetch = (uri, options) => { return fetch(uri, options) .then(response => { if (response.status >= 500) { // or handle 400 errors return Promise.reject(response.status); } return response; }); }; const client = new ApolloClient({ link: createHttpLink({ uri: "/graphql", fetch: customFetch, }), cache: new InMemoryCache() });Thanks for that solution works a treat
Also if you are using React remember you can proxy requests to your backend by entering the url in the package.json
Hello, I have the same issue using version 3.0.0-beta.43.
Here's my details:
latest console.log (After being logged in, user is not confirmed so I am redirecting to this ConfirmEmailScreen where I am doing a lazy query polling every 5secs and after some I got the issue)
authentication.ts:26 {access-token: "CIBBhg9Y-W2QQrQoIQlIIQ", client: "htH6v6_UMpm6UAtbgFhfdw", token-type: "Bearer", expiry: "1588783816", uid: "[email protected]"}
SignIn.tsx:64 {data: {…}}
ConfirmEmail.tsx:53 exit condition not true yet. continue polling
AuthNavigator.tsx:42 AuthNavigator got signedIn, so updated navigation...
ConfirmEmail.tsx:40 started polling
ConfirmEmail.tsx:53 exit condition not true yet. continue polling
authentication.ts:26 {access-token: "ZsYqtJkfw_3LVIv1YQGm4g", client: "1F7yOM_2RkFC0L6Wg5e0AQ", token-type: "Bearer", expiry: "1588784117", uid: "[email protected]"}
2ConfirmEmail.tsx:53 exit condition not true yet. continue polling
authentication.ts:26 {access-token: "ZsYqtJkfw_3LVIv1YQGm4g", client: "1F7yOM_2RkFC0L6Wg5e0AQ", token-type: "Bearer", expiry: "1588784117", uid: "[email protected]"}
apollo-client.ts:28 [Network error]: ServerParseError: Unexpected token < in JSON at position 0
ConfirmEmail.tsx:47 error! stopped polling
and the code:
const ConfirmEmailScreen = ({navigation}) => {
const {emailConfirmed} = React.useContext(AuthContext);
const _isPolling = useRef(false);
const [
getUserMe,
{loading: loadingUserMe, error, data: dataUserMe, stopPolling}
] = useLazyQuery(QUERY_USER_ME, {
pollInterval: 5000
});
const [userResendConfirmationEmail, {loading: resendLoading}] = useMutation(
MUTATION_USER_RESEND_CONFIRMATION
);
const onResendPress = () => {
userResendConfirmationEmail()
.then((res) => {
console.log(res);
})
.catch((reason) => {
console.log(reason);
});
};
useEffect(() => {
if (!_isPolling.current) {
console.log('started polling');
getUserMe();
_isPolling.current = true;
}
});
if (error) {
console.log('error! stopped polling');
stopPolling();
} else if (dataUserMe && dataUserMe.me && !!dataUserMe.me.confirmedAt) {
stopPolling();
emailConfirmed(dataUserMe.me);
} else {
console.log('exit condition not true yet. continue polling');
}
return (
<SafeAreaView style={[styles.containerPadding, styles.contentCentered]}>
<Text style={[styles.mb16, styles.textCenter]}>
We sent an email. Please check your mailbox at{' '}
{dataUserMe && dataUserMe.me ? dataUserMe.me.email : ''}
</Text>
{!error ? (
<ActivityIndicator
style={styles.mb16}
animating={true}
color={Colors.black}
/>
) : null}
{error ? (
<Text style={[styles.errorText, styles.mt16]}>
Server/Apollo error, polling has been stopped
</Text>
) : null}
<Button mode="contained" loading={resendLoading} onPress={onResendPress}>
Send again
</Button>
</SafeAreaView>
);
};
Do you have any suggestions?🙏🏻 Or am I doing something wrong?

I have the same error but I deployment my server-app in heroku this server work but when try the connect me from my app in react-native, show me the screen initial but i want SignIn and I have this error:
react-apollo Error: Network error: Unexpected token < in JSON
@Patricio18 I found out the code is correct and it was due to a backend issue (an experimental feature active on Apollo Rails side). This error represents a "right" parsing error of a html page, a redirect response.
Flipper debugger (standalone app) helped my network troubleshooting a lot🙌.
Hope this helps.
For myself, I solved the problem of showing custom errors from the server:
you need add accept: 'application/json' to apollo headers request;
then if you catch error - stringify it ( JSON.stringify(error, null, 2)) ) to to find out all available properties.
Without indication accept: 'application/json' i was getting html-content error (which was parsed with an error).
const authLink = setContext(async (_, { headers, ...context }) => {
const jwt = await _asyncGetString('jwt');
const settings = {
headers: {
...headers,
accept: 'application/json',
...(jwt ? { authorization: `Bearer ${jwt}` } : {})
},
...context
};
return settings;
});
const client = new ApolloClient({
link: ApolloLink.from([authLink, httpLink]),
cache: new InMemoryCache()
});
"graphQLErrors": [],
"networkError": {
"name": "ServerError",
"response": {
"type": "default",
"status": 401,
"ok": false,
"headers": {
"map": {
"server": "nginx/1.14.0 (Ubuntu)",
...
}
},
"url": “…./graphql/contest",
"bodyUsed": true
},
"statusCode": 401,
"result": {
"message": "Token Signature could not be verified.",
"exception": "Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException",
"file": "...vendor/tymon/jwt-auth/src/Http/Middleware/BaseMiddleware.php",
"line": 74,
"trace": [
{
"file": "...vendor/tymon/jwt-auth/src/Http/Middleware/Authenticate.php",
"line": 30,
"function": "authenticate",
"class": "Tymon\\JWTAuth\\Http\\Middleware\\BaseMiddleware",
"type": "->"
},
...
}]
}
},
"message": "Network error: Response not successful: Received status code 401"
I get data in the status of 200, and everything is displayed normally, but any error that comes is not processed by the Apollo and writes the error:
"Error:" Network error: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data "
Although I get this error in status 200
{"errors": [{"message": "Provided JWT token is invalid", "locations": [{"line": 2, "column": 3}], "path": ["user"], " extensions ": {" details ":" Wrong JWt "}}]}
const linkHttp = new HttpLink({
uri: 'http://localhost:3033/graphql',
headers: {
Authorization: Bearer Token,
accept: 'application/json',
'Content-Type': 'application/json'
},
...(process.env.NODE_ENV !== 'production'
? { fetchOptions: {
mode: 'no-cors',
} } : {}),
credentials: 'same-origin'
})
const client = new ApolloClient({
link: ApolloLink.from([
linkError,
linkHttp
]),
cache: new InMemoryCache()
});
Don't worry. We can fix it in simple way.
the first, fault we are doing is
importing ApolloClient from 'apollo-boost'. Actually we have to import ApolloClient from 'apollo-client'.
import ApolloClient from 'apollo-client';
Because, ApolloClient from apollo-boost only supports a smaller subset of configuration options. ApolloClient from apollo-client gives you all the configuration options.
then we can provide link and cache only to Apollo-client instance
import { InMemoryCache } from "apollo-cache-inmemory";
import { createHttpLink } from 'apollo-link-http';
const client = new ApolloClient({
link: new createHttpLink(
{
uri: "Your QraphQL Link"
}
),
cache: new InMemoryCache(),
});
That's it
Don't worry. We can fix it in simple way.
the first, fault we are doing is
importing ApolloClient from 'apollo-boost'. Actually we have to import ApolloClient from 'apollo-client'.
import ApolloClient from 'apollo-client';Because, ApolloClient from apollo-boost only supports a smaller subset of configuration options. ApolloClient from apollo-client gives you all the configuration options.
then we can provide link and cache only to Apollo-client instance
import { InMemoryCache } from "apollo-cache-inmemory"; import { createHttpLink } from 'apollo-link-http'; const client = new ApolloClient({ link: new createHttpLink( { uri: "Your QraphQL Link" } ), cache: new InMemoryCache(), });That's it
I know about it.
And use apollo-client.
my solution was to use nginx. because my server is not written on Apollo Server, but on rust. And for some reason, on a localhost in dev mode, I required Cors during requests. I put the no-cors mod. And that broke the ability to send a type / json request. I’m already seen many this issues, and it’s not clear why the Apolo team will not fix this problem for devs on localhost and I have to install nginx.
A tidbit of info for others dealing with this error:
I was using the 'useGETForQueries' option in createHttpLink() which caused the error if a Fragment was missing. Turning that off, solved the problem.
const link = createHttpLink({
uri: endpoint,
useGETForQueries: false
})
I'm seeing this in some legitimate use cases that aren't fixable on the server, eg. when the front-end webserver (Traefik or nginx) times out a long request, or when the host is unreachable. The problem seems to come from this code:
export function parseAndCheckHttpResponse(
operations: Operation | Operation[],
) {
return (response: Response) => response
.text()
.then(bodyText => {
try {
return JSON.parse(bodyText);
} catch (err) {
const parseError = err as ServerParseError;
parseError.name = 'ServerParseError';
parseError.response = response;
parseError.statusCode = response.status;
parseError.bodyText = bodyText;
throw parseError;
}
})
A 504 Gateway Timeout may always return an HTML document. In this case, attempting to parse it as JSON results in the err.message property being set to "Unexpected token < in JSON at position 0", which incorrectly masks the underlying issue.
Complicating this, MockedProvider by design does not invoke the typical Apollo Client code path (shown above), so we're not able to write unit tests for solutions eg. using Error Link. However, I was able to write a unit test by invoking the real ApolloProvider and my ApolloClient instance by mocking network requests via the excellent nock library:
import { ApolloProvider, gql, useQuery } from '@apollo/client'
import { render, waitFor } from '@testing-library/react'
import nock from 'nock'
import React from 'react'
import { apolloClient } from '.'
const mockQuery = gql`
query foo {
bar
}
`
const TestComponent = () => {
const { error } = useQuery(mockQuery)
return <div data-testid="error-message">Error: {error?.message}</div>
}
const queryBody =
'{"operationName":"foo","variables":{},"query":"query foo {\\n bar\\n}\\n"}'
beforeEach(() => {
nock.disableNetConnect()
})
afterEach(() => {
nock.cleanAll()
nock.enableNetConnect()
})
it('displays error messages when not JSON', async () => {
// Allow localhost connections so we can test local routes and mock servers.
nock.enableNetConnect('127.0.0.1')
nock('http://localhost/')
.post('/graphql', queryBody)
.reply(504, '<table>Gateway timeout</table>')
const { getByTestId } = render(
<ApolloProvider client={apolloClient}>
<TestComponent />
</ApolloProvider>
)
await waitFor(() =>
expect(getByTestId('error-message')).toHaveTextContent(
'Error: <table>Gateway timeout</table>'
)
)
})
Of course, you will want to use MockedProvider for the vast majority of your Apollo components due to its ease of use, but I hope this method helps anyone struggling to fix this issue.
Restarting my mac solved the issue !
Most helpful comment
His server is at fault, but this error message shows apollo-client also misbehaving.
If a response comes back with a status code 502, 404, or really anything other than 200, and especially with a content-type indicating the response is HTML, I don't think apollo-client should try to decode it as JSON.
It's not really a big deal, but at the very least the error message produced by querying a missconfigured server could be improved.