Next/Form Does Not Normalize Newlines In GET Submissions After Hydration
Client-side next/form string actions append FormData entries to URLSearchParams without normalizing line endings according to the HTML specification, causing LF-only line breaks instead of CRLF.
In form-shared.tsx, the function building URLSearchParams from FormData iterates over entries and appends raw values without applying the HTML form submission algorithm's line-ending normalization (replacing CR not followed by LF and LF not preceded by CR with CRLF).
1. Create a Next.js app with a next/form string action. 2. Add a textarea with defaultValue containing a LF newline (e.g., 'line1\nline2'). 3. Submit the form after hydration. 4. Observe server receives 'line1\nline2' instead of 'line1\r\nline2'.
Fixing Code Block
// In packages/next/src/client/form-shared.tsx
// Replace the function that builds URLSearchParams from FormData (around line 80) with:
function normalizeLineEndings(value: string): string {
let result = '';
for (let i = 0; i < value.length; i++) {
const char = value[i];
if (char === '\r') {
if (i + 1 < value.length && value[i + 1] === '\n') {
result += '\r\n';
i++; // skip LF as part of CRLF
} else {
result += '\r\n';
}
} else if (char === '\n') {
// LF not preceded by CR (otherwise it would have been handled at the CR iteration)
result += '\r\n';
} else {
result += char;
}
}
return result;
}
export function getFormDataFromFormElement(formElement: HTMLFormElement) {
const formData = new FormData(formElement);
const urlSearchParams = new URLSearchParams();
for (const [key, value] of formData.entries()) {
urlSearchParams.append(normalizeLineEndings(key), normalizeLineEndings(value));
}
return urlSearchParams;
}
Adds a normalizeLineEndings helper implementing the HTML spec rule: replace every CR not followed by LF and every LF not preceded by CR with CRLF. Then applies it to both key and value when building URLSearchParams from FormData.
Edge Case Audit
The change alters line endings in client-side GET form submissions to match native behavior. Existing applications that relied on LF-only values will now receive CRLF, potentially affecting string comparisons or server-side parsing. This change only affects client-side string action GET submissions; server-side rendering and native form posts remain unchanged. Rollback: revert the added normalization helper and restore the direct append call if regressions occur. Test with forms that include newline characters and ensure downstream processing handles CRLF.