facebook/react · warning · Error
File/Blob fields are not yet supported in progressive forms.
Error message
File/Blob fields are not yet supported in progressive forms. Will fallback to client hydration.
What it means
React's Fizz server renderer validates the FormData attached to a form action (via the action's $$FORM_ACTION metadata, e.g. bound arguments of a Server Action) when it tries to serialize the form for progressive enhancement (a form that works before JS loads). Hidden inputs can only encode string values, so any File/Blob entry in that FormData fails validation. The throw happens inside getCustomFormFields, which catches it, logs 'Failed to serialize an action for progressive enhancement' in DEV, and silently downgrades the form to client-hydration-only replay, so the render does not crash.
Source
Thrown at packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:1424
validateAdditionalFormField(value, key);
pushStringAttribute(target, 'name', key);
pushStringAttribute(target, 'value', value);
target.push(endOfStartTagSelfClosing);
}
function pushAdditionalFormFields(
target: Array<Chunk | PrecomputedChunk>,
formData: void | null | FormData,
) {
if (formData != null) {
// $FlowFixMe[prop-missing]: FormData has forEach.
formData.forEach(pushAdditionalFormField, target);
}
}
function validateAdditionalFormField(value: string | File, key: string): void {
if (typeof value !== 'string') {
throw new Error(
'File/Blob fields are not yet supported in progressive forms. ' +
'Will fallback to client hydration.',
);
}
}
function validateAdditionalFormFields(formData: void | null | FormData) {
if (formData != null) {
// $FlowFixMe[prop-missing]: FormData has forEach.
formData.forEach(validateAdditionalFormField);
}
return formData;
}
function getCustomFormFields(
resumableState: ResumableState,
formAction: any,
): null | ReactCustomFormAction {View on GitHub (pinned to eafeac097b)
Solutions
- Do not bind File/Blob entries into the server action — extract only serializable string values (filenames, ids, text fields) into the closure/bind args
- Read files from the submitted FormData inside the action (form inputs are transmitted with the form anyway) instead of pre-binding them
- If a file upload must work without JS, point the form at a plain route handler or API endpoint instead of a server action
- In a custom $$FORM_ACTION implementation, filter data down to string entries before returning it
Example fix
// before
const action = uploadAction.bind(null, formDataWithFiles); // FormData contains File entries
<form action={action}>...</form>
// after: bind only strings; read files from the submission itself
const action = uploadAction.bind(null, formDataWithFiles.get('docName'));
<form action={action}>
<input type="file" name="doc" />
</form> Defensive patterns
Strategy: validation
Validate before calling
function hasOnlyStringFields(formData: FormData): boolean {
let ok = true;
formData.forEach((value) => {
if (typeof value !== 'string') ok = false;
});
return ok;
}
// before binding:
// const bound = hasOnlyStringFields(fd) ? uploadAction.bind(null, fd) : uploadAction; Type guard
function isFileEntry(v: FormDataEntryValue): v is File {
return typeof v !== 'string'; // File/Blob is the only non-string FormDataEntryValue
} Try / catch
// Not applicable to userland: React catches this internally in getCustomFormFields and only logs a DEV console.error ('Failed to serialize an action for progressive enhancement'), then falls back to client replay. Prevention
- Never bind File or Blob values into server actions; bind only strings, numbers, and serializable primitives
- Read file inputs from the FormData the browser submits, not from closure state
- Test forms with JavaScript disabled to detect lost progressive enhancement early
- In custom $$FORM_ACTION implementations, filter data to string entries before returning
When it happens
Trigger: Rendering <form action={fn}> during SSR where fn is a server action whose $$FORM_ACTION(prefix) returns customFields.data containing a File or Blob value — typically a server action bound (via .bind or a closure) to a FormData that came from a file input (e.g. request.formData() with type="file" fields), used with <form action> or useActionState progressive enhancement.
Common situations: Next.js App Router or RSC apps with file-upload forms built on server actions; binding a captured FormData (which includes files) into an action; custom createServerReference/registerServerReference implementations whose $$FORM_ACTION returns file entries. The page still works after hydration, so the only visible symptom is the DEV console.error and forms that do nothing before JS loads.
Related errors
- 582
- Server Functions cannot be called during initial render. Thi
- Server Functions cannot be called during initial render. Thi
- Server Functions cannot be called during initial render. Thi
- Server Functions cannot be called during initial render. Thi
AI-assisted analysis of facebook/react@eafeac097b (2026-08-21).
Data as JSON: /api/errors/17ded354bdadb98c.
Report an issue: GitHub.