nuxt: useAsyncData does not pass errors from server to client-side
Environment
- Operating System:
Linux
- Node Version:
v14.18.1
- Nuxt Version:
3.0.0-27294839.7e5e50b
- Package Manager:
yarn@1.22.15
- Bundler:
Vite
Reproduction
https://stackblitz.com/edit/github-ygz9df?file=app.vue
Describe the bug
On server side the error content is rendered as expected while the client side says it’s null.
Additional context
No response
Logs
No response
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 6
- Comments: 26 (5 by maintainers)
@nndnha I understand. One note: if you need to get the status code on client side and don’t mind an extra request, you can also rerun the fetch.
Another solution would be to change your backend server to return status 200 instead of 4xx for usage errors, that way you can read the error message/code from the payload and nothing private from the Nuxt server would be exposed.
After a bit of search trough the ohmyfetch (the library used by nuxtjs mentioned in the documentation) I obtained the status code easily, this is my solution:
This is my first response to a GitHub issue, hope i wrote it at least understandable
For
FetchError
, I want to get the http status code.I tweaked this solution a little so it can be reusable:
Then somewhere in your app
@pi0 I’m not using the error content for rendering, I want to use its content to make some checks on rendering. I want to detect the response status code whenever it’s 400, 404, 401, 403, 5xx… We won’t retry on 4xx errors without alteration to the request parameters, won’t we?
@pi0 @danielroe In
useAsyncData
we havetransform
option to transform the result data, how about if we add another option calledtransformError
to alter the error? The default value of thetransformError
option can be a function that returns a simple data likes(error) => error.toString()
or() => "An generic error message here..."
to reduce the payload size. Then in my case I will able to get my favorite status code by providing my customtransformError
:No. Status codes are there for a reason. A serverside application returns a 404 for a reason: I cannot find what you are looking for. Give me the bloody error. I have no information with a boolean. I do not know if there is an internal server error, if a request is malformed, etc. Nuxt should not every decide for me that I am an absolute beginner thus that they need to hide useful error data.
And might include data in that response body. 404 is pretty self explanatory, but a 400 might include a message as to why your request is malformed.
This would be a perfect way of solving the problem imo.
I’m experiencing the same issue as @nndnha, in that I want the status code on the client side. For me it’s to show appropriate error UI, so that my users know exactly what’s gone wrong.
My way of solving this until now was for some useFetchs (well, technically useLazyAsyncDatas, but who’s counting) to only run on the client side, to ensure I have the full error context. In all cases, I was only ever looking at the status code anyway, and had a computed property to extract that from the rest of the context.
I think my ideal situation would be for the error property to always just be the error code, but I can see that there are cases where the rest of the error context could be useful, so being able to write a custom transformation strikes the perfect balance - offering full flexibility and ease of use, without making any assumptions for you.
I will also say that I appreciate Nuxt defaulting to hiding the error context because of the potential security issue it could cause - this is definitely the right approach to take for a default action (even if it does slightly hinder developer UX), and gives me great greater confidence that I’m not exposing myself to another issue somewhere else because I forgot to overwrite another default. Security first, additional functionality second.
I think both are valid points here. While
error
reference should be accessible per env for logging purposes, It is not meant for being serialized to payload or using its content to render.Standard usage would be: (note that error is used as a boolean –
hasError
)BTW if you really want to expose message, you can explicitly leak it with another state:
@danielroe BTW we might do better error hydration on the client-side, using a new Error instead of changing the type to boolean or probably better always make it boolean as
hasError
and provide a callback foronError
handling by user this can also give a chance of implementing retry/fallback strategies easier.It would be very helpful for me to have access to the error details. A request can fail for several reasons. Maybe the user is trying to access something that they haven’t been authorized to access, in which case we might inform the user of this (and possibly suggest that they request access from the owner). Or maybe the user made a typo and they’re (accidentally) trying to access something that doesn’t exist, in which case we might tell the user to check for typos. Or maybe the server is down, in which case we might provide the user with a “Try Again” button.
There is already some way to easily get the body when response code is other than 200?
Well-written rest API returns various error codes
In my case, I used promises.
Fair point about retrying on specific errors. Thinking how we can improve
_errors
then (into more general_state
) that can sync state between client and server + next step after hydration (retry or error)@danielroe Thanks for that solution, but @pi0 does care about the performance right? An extra duplicate request is a performance penalty for both server(internal server instead of
jsonplaceholder.typicode.com
) and client.