createFileRoute() and createServerFn() loader type error with Vercel AI-SDK.
I get a type error in a createFileRoute() or createServerFn() loader when returning AI SDK UIMessage types. The problem is UIMessage has unknowns deeply embedded in the type structure that can't be controlled from the outside ('dynamic-tool' message parts, in particular).
I realize this is because you don't know if "unknown" will be serializable. But in a case like this, I can't control the type, and we know it will be serializable because that's the purpose of AI-SDK's UIMessage.
What's the best way to work around this case?
4 Replies
absent-sapphireOP•2mo ago
I just realized this exact issue exists in Github too: https://github.com/TanStack/router/issues/5229
But @Manuel Schiller 's suggestion to explicitly type the metadata in that issue doesn't solve the problem, as some of the unknowns are in dynamic tool types that the AI-SDK adds, and that can't be specified from the outside.
Specifically, here's the problem with AI-SDK's UIMessage:
UIMessage contains
parts: Array<UIMessagePart<DATA_PARTS, TOOLS>>.
And UIMessagePart is
DynamicToolUIPart and ToolUIPart<TOOLS> both have this problem. For example, here is the relevant part of DynamicToolUIPart :
'output-available' and 'output-error' state have unknowns, and they're not controllable from the outside.
I think the only viable options are to recreate the type manually or do typescript surgery on UIMessage type to replace the DynamicToolUIPart with one with more concrete types...
Me and GPT-5 did some work and came up with what I think is the minimal "fix" , replacing unknowns with JSONValue:
EDIT: updated the above since I found another case of unknowns in normal static tools too.
This may be enough to make it work, but it took me a few hours to figure out all the pieces and it's pretty tricky surgery just to be able to return a AI-SDK UIMessage from server to client.extended-salmon•5w ago
we are thinking about a way to opt out of this check for selected server functions. but you must be aware that any of those unknowns could contains something that is not serializable at runtime and this will break then
absent-sapphireOP•5w ago
That sounds good. I understand it's a pandora's box, but in this case UIMessage exists specifically to be sent to the client. Oh, and thank you for the reply! Loving Tanstack Start so far.
One more note: the error message when returning something with unknown in it is not obvious. I don't know if that's fixable but it took me a while to even realize this was an issue of returning unknown.
extended-salmon•5w ago
@Chris Horobin can we hack the typescript error to be a bit more declarative here?