Validation returns raw form value instead of parsed value (standard schema validators)
Describe the bug
When validating with a “standard” schema, the form returns the original (unparsed) value instead of the schema-parsed value. This causes:
- Untrusted raw values from the frontend to bypass validation/sanitization, which is unsafe.
- Common transformation use cases (e.g., trimming, type coercion, normalization) to be skipped.
Your minimal, reproducible example
https://stackblitz.com/edit/stackblitz-starters-doaombkp?file=app%2Fpage.tsx
Steps to reproduce
- Click the Submit button.
- Inspect the result: you can confirm the unparsed value under the
actualkey.
Expected behavior
On successful validation (no issues), the validator should return the parsed value.
How often does this bug happen?
Every time
Screenshots or Videos
Platform
- MacOS
- Chrome
TanStack Form adapter
react-form
TanStack Form version
1.19.3
TypeScript version
5.2.2
Additional context
Proposed change:
packages/form-core/src/standardSchemaValidator.ts: L82
- if (!result.issues) return;
+ if (!result.issues) return { ok: true, data: result.value };
packages/react-form/src/nextjs(remix,start)/createServerValidate.ts
- const onServerError = await runValidator({
- value: values,
- validationSource: "form"
- });
- if (!onServerError) return values;
+ const validated = await runValidator({
+ value: values,
+ validationSource: "form"
+ });
+ if (validated.ok) return validated.data;
I believe this is expected behaviour: https://tanstack.com/form/v1/docs/framework/react/guides/submission-handling#transforming-data-with-standard-schemas
While Tanstack Form provides Standard Schema support for validation, it does not preserve the Schema's output data.
My concern is on the server side — specifically, that the createServerValidate function isn’t working.
I'm using transforms with valibot like:
const CorsOriginsSchema = v.pipe(
v.string(),
v.transform((value) => {
if (value.trim() === "") {
return [];
}
return value.split(",").map((origin) => origin.trim());
})
);
and I need to call an api with the transformed output type of the schema so I seem to need to run it twice:
const form = useAppForm({
defaultValues,
validators: {
onSubmit: SomeFormSchema
},
onSubmit: async (theForm) => {
// Validator already checked validity, but didn't apply transforms.
// Parse again to get the transformed output type.
// Since validator passed, this parse is guaranteed to succeed.
// FIXME: there's gotta be a better way?
const transformedData = v.parse(SomeFormSchema, theForm.value);
await doStuff({ transformedData });
}
});
This is per the suggestion at https://tanstack.com/form/v1/docs/framework/react/guides/submission-handling#transforming-data-with-standard-schemas, but I don't like it…
I understand this might be a hard problem, but maybe there's a simple way to just remove the "validators" field here and do manual validation in the onSubmit, but programmatically kinda one-liner?
I mean in this case with valibot that would be with safeParse, something like:
const result = v.safeParse(SomeFormSchema, theForm.value);
if(result.success)
await doStuff({ result.output });
else {
pushTheErrors(result.issues)
}
I guess the issue is to transform the result.issues valibot specific structure to the tanstack form way and I guess there is code somewhere to do that, but I can't easily find it.
Anyway, I'd be fine with that solution, but running twice feels smelly to me.
I just stumbled upon this as well. I'm glad it was mentioned in the docs, Took quite a while to figure out where the bug in our system was coming from. But I would really expect/prefer the transformed values to be returned, not the og input. Maybe as a separate property if we want to keep things backwards compatible?
onSubmit: ({value, transformedValue}) => doStuff(transformedValue)
@kabo the issue with combining all the types from different validators still persists