try {
const result = await ky.post('/somepaththaterrors', {
json: {
// orsomeparametersthaterrors
},
}).json();
} catch (error) {
alert(error.message); // Bad Request
}
If on express we do res.status(400).send('Some error here');, ky's error.message will be "Bad Request" and not "Some error here".
Chrome's Console Network -> XHR requests tab will show that the request returned a response body containing "Some error here" but if we try to traverse the error object, there is no path or property that leads us to the returned response body "Some error here"
Is this the intended outcome? I was just thinking that the body of a 4XX response could let us relay additional information on what makes the request a Bad Request.
We do provide the response for non-2xx status codes. See the documentation on our HTTPError class, which is mentioned in a few places.
You can access the response as error.response. From there, you can access the body the same way you would using fetch() or any other API that returns a Response instance.
One thing to keep in mind is that error will only have a response if we, well... received a response. So for example, if you turn your Wi-Fi off and try to make a request with Ky, we will throw an error, but error.response will be undefined. You should handle that case in your code.
Hi @sholladay, thanks for responding.
I've seen the response object is accessible within the error, but the body is just a ReadableStream? (images provided)
It also has .text() and .json() methods but they only return a DOMException.
// express
app.post('/path-that-returns-400-with-response-body', async (req, res) => {
res.status(400).send('Some error here');
});
// client
try {
await ky.post('/path-that-returns-400-with-response-body', {
json: {
// anything
},
});
} catch (error) {
console.log({ error });
}



Nevermind, solved it.
@sholladay I am also trying to access error.response to see the body on non 2xx responses.
Do you have a complete example of how I can do this? Maybe it could also be added to the Readme for people (like me) who are less experienced with http api's.
I'm especially having trouble understanding what this part of the documentation means and how I can use it:
ky.HTTPError
Exposed for instanceof checks. The error has a response property with the Response object.
@sholladay I have the same problem where I try to access the response body by error.response but it just says ReadableStream.
Can you share your solution please?
Sure, I'll walk you through it.
ky.HTTPError
This is referencing the _class_ HTTPError, which is something that Ky defines and exports so that you can more easily identify HTTP errors when they happen, by checking whether a given error is an instance of HTTPError.
Exposed for instanceof checks.
This is what I was talking about above. Basically, the class is useful because you can write if (error instanceof ky.HTTPError) { in your code to check if an error is specifically an HTTP error, as opposed to, say, a network error.
The error has a response property with the Response object.
Here, "the error" is any instance of HTTPError. So it's saying that all HTTP errors thrown by Ky will have a property named response that is an instance of the Response class. See MDN for details about what a Response instance is like and how to use it. In short, it is a stream (as you mentioned), which represents some data that Ky has received from a server. Inside of the response is a status code, headers, and maybe a body.
There are a number of different ways to read the value of the response body, which is likely what you want to do. Specifically, you can use any of the methods from the Body class, because Response implements the Body methods as well as some of its own.
Let's say that your server responds with a 404 and a simple text message saying "Sorry, page not found." You could read that message from the response like this...
const run = async () => {
try {
await ky.get('/nonexistent').json();
}
catch (error) {
const serverMessage = await error.response.text();
console.log('Server error: ' + serverMessage);
}
};
If your server returns JSON for a 404 instead of text, then you could use .json() instead of .text() in the example above. These are the same methods you use with Ky to fetch a normal response body when a 2xx status code is received. The only difference is that in the case of an error, you're calling them on error.response instead of the response returned by Ky directly.
If you want it as an object make sure to use .json() instead of text
Most helpful comment
Sure, I'll walk you through it.
This is referencing the _class_
HTTPError, which is something that Ky defines and exports so that you can more easily identify HTTP errors when they happen, by checking whether a given error is an instance ofHTTPError.This is what I was talking about above. Basically, the class is useful because you can write
if (error instanceof ky.HTTPError) {in your code to check if an error is specifically an HTTP error, as opposed to, say, a network error.Here, "the error" is any instance of
HTTPError. So it's saying that all HTTP errors thrown by Ky will have a property namedresponsethat is an instance of theResponseclass. See MDN for details about what aResponseinstance is like and how to use it. In short, it is a stream (as you mentioned), which represents some data that Ky has received from a server. Inside of the response is a status code, headers, and maybe a body.There are a number of different ways to read the value of the response body, which is likely what you want to do. Specifically, you can use any of the methods from the
Bodyclass, becauseResponseimplements theBodymethods as well as some of its own.Let's say that your server responds with a 404 and a simple text message saying "Sorry, page not found." You could read that message from the response like this...
If your server returns JSON for a 404 instead of text, then you could use
.json()instead of.text()in the example above. These are the same methods you use with Ky to fetch a normal response body when a 2xx status code is received. The only difference is that in the case of an error, you're calling them onerror.responseinstead of the response returned by Ky directly.