One incredibly important part of streaming is handling errors. There are many, many different things that can go wrong in the AI SDK - and the way it handles errors is really nice.
Because we are streaming to the front end, if there's ever an error that happens in the stream, then it will simply stream that error to the front end. However, you may want to show a nicer error message than the AI SDK provides by default.
I've set up some demo code here that creates a UI message stream that immediately throws a retry error. This mimics what would happen if streamText errored.
import { createUIMessageStream, RetryError } from 'ai';const stream = createUIMessageStream({execute: async ({ writer }) => {throw new RetryError({errors: [new Error('An error occurred')],message: 'Maximum retries exceeded',reason:
onError HandlerAny error that happens inside this execute function gets bubbled up to this onError handler. And here's where we see our first TODO. It's to check if the error is a RetryError using RetryError.isInstance, and if it is, we're going to return a message that tells the user to try again.
onError(error) {// TODO: Check if the error is a RetryError using:// RetryError.isInstance(error)if (TODO) {// TODO: If it is, return a message that tells the user to try againreturn TODO;}// TODO: Return a default message if the error is not a RetryErrorreturn TODO;}
If we can't identify the error using RetryError.isInstance, then we're going to return a default message if the error is not a retry error. Something like "an unknown error occurred."
Once that's all hooked up, it's now time to actually show it in the front end. Here's the App component:
const App = () => {// TODO: Destructure the error property returned from the useChat hookconst { messages, sendMessage } = useChat({});const [input, setInput] = useState(`What's the capital of France?`,
Our first job is to go into useChat and destructure out the property of error here. This error is going to be an error object which has a message on it.
We have a component below called ErrorMessage which will just show the message with a nice little lucid icon:
const ErrorMessage = ({ error }: { error: Error }) => {return (<div className="flex items-center gap-2 p-3 mb-4 text-red-300 bg-red-900/20 border border-red-500/30 rounded-lg"><AlertCircle className="size-5 flex-shrink-0" /><span>{error.message}</span></
So your job is to show the error message if the error exists. And I think under the messages is a decent place for it.
Once that's done, you should be able to run the code and send any message to the back end and it will immediately show an error message. Good luck, and I'll see you in the solution.