Link to the code that reproduces this issue
https://github.com/Tnalxmsk/next-form-newline-repro
To Reproduce
- Clone the linked repository and open its directory.
- Run
npm ci, then npm run build, followed by npm run start.
- Open
http://localhost:3000/newline and wait for Hydrated: true.
- Leave the textarea unchanged and click Submit native. Inspect
serverSearch.text on the result page.
- Return to
/newline, wait for Hydrated: true, and click Submit next without changing the textarea.
- Compare
serverSearch.text between the two submissions.
The same steps can also be run with npm run dev instead of the production build and start commands.
Both forms contain the same textarea with defaultValue={'line1\nline2'}. The submit buttons have no name or value attributes. No environment variables, external APIs, or account access are needed to run the reproduction.
Current vs. Expected behavior
Current behavior**
The native HTML form and hydrated next/form submit different strings for the same textarea content:
| Submission |
Server-received text |
Encoded query value |
| Native HTML form |
"line1\r\nline2" |
line1%0D%0Aline2 |
| Hydrated Next.js Form |
"line1\nline2" |
line1%0Aline2 |
The difference is present in the server's searchParams, not just the address bar. The single-line control value is preserved in both submissions.
Expected behavior
A string-action Next.js Form should normalize line endings to CRLF, matching a native HTML GET form.
The Next.js Form documentation describes string actions as behaving like native GET forms. The HTML form submission algorithm normalizes standalone CR and LF characters in field names and values to CRLF before URL encoding.
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 25.5.0: Mon Apr 27 20:40:51 PDT 2026; root:xnu-12377.121.6~2/RELEASE_ARM64_T8112
Available memory (MB): 16384
Available CPU cores: 8
Binaries:
Node: 24.2.0
npm: 11.3.0
Yarn: 1.22.22
pnpm: 11.24.0
Relevant Packages:
next: 16.4.0-canary.22 // Latest available version is detected (16.4.0-canary.22).
eslint-config-next: N/A
react: 19.2.1
react-dom: 19.2.1
typescript: N/A
Next.js Config:
output: N/A
Which area(s) are affected? (Select all that apply)
Form (next/form)
Which stage(s) are affected? (Select all that apply)
next dev (local), next start (local)
Additional context
- Previous report: #98404. It was automatically closed after the reproduction checker received HTTP 403 from the CodeSandbox URL. This report uses a public GitHub reproduction repository instead.
- Locally reproduced with Next.js 16.3.4 and 16.4.0-canary.22, React/ReactDOM 19.2.1, and Node 24.2.0, in both development and production. Both production builds succeeded.
- The optional CodeSandbox preview was separately verified in production with Next.js 16.4.0-canary.22, React/ReactDOM 19.2.1, and Node 20.12.0.
- Browser used for verification: Chromium-based ego-browser on macOS, with a Chrome/150.0.0.0 user agent.
- In a separate local production check, blocking
/_next/static/* requests and confirming Hydrated: false before submission caused Next.js Form to submit CRLF, like the native form. The LF result occurs after hydration.
- The relevant implementation creates
new FormData(formElement) and then appends the entries directly to URLSearchParams, without normalizing line endings: form-shared.tsx.
- The first affected release has not been identified.
Link to the code that reproduces this issue
https://github.com/Tnalxmsk/next-form-newline-repro
To Reproduce
npm ci, thennpm run build, followed bynpm run start.http://localhost:3000/newlineand wait for Hydrated: true.serverSearch.texton the result page./newline, wait for Hydrated: true, and click Submit next without changing the textarea.serverSearch.textbetween the two submissions.The same steps can also be run with
npm run devinstead of the production build and start commands.Both forms contain the same textarea with
defaultValue={'line1\nline2'}. The submit buttons have nonameorvalueattributes. No environment variables, external APIs, or account access are needed to run the reproduction.Current vs. Expected behavior
Current behavior**
The native HTML form and hydrated
next/formsubmit different strings for the same textarea content:text"line1\r\nline2"line1%0D%0Aline2"line1\nline2"line1%0Aline2The difference is present in the server's
searchParams, not just the address bar. The single-line control value is preserved in both submissions.Expected behavior
A string-action Next.js Form should normalize line endings to CRLF, matching a native HTML GET form.
The Next.js Form documentation describes string actions as behaving like native GET forms. The HTML form submission algorithm normalizes standalone CR and LF characters in field names and values to CRLF before URL encoding.
Provide environment information
Operating System: Platform: darwin Arch: arm64 Version: Darwin Kernel Version 25.5.0: Mon Apr 27 20:40:51 PDT 2026; root:xnu-12377.121.6~2/RELEASE_ARM64_T8112 Available memory (MB): 16384 Available CPU cores: 8 Binaries: Node: 24.2.0 npm: 11.3.0 Yarn: 1.22.22 pnpm: 11.24.0 Relevant Packages: next: 16.4.0-canary.22 // Latest available version is detected (16.4.0-canary.22). eslint-config-next: N/A react: 19.2.1 react-dom: 19.2.1 typescript: N/A Next.js Config: output: N/AWhich area(s) are affected? (Select all that apply)
Form (next/form)
Which stage(s) are affected? (Select all that apply)
next dev (local), next start (local)
Additional context
/_next/static/*requests and confirming Hydrated: false before submission caused Next.js Form to submit CRLF, like the native form. The LF result occurs after hydration.new FormData(formElement)and then appends the entries directly toURLSearchParams, without normalizing line endings: form-shared.tsx.