vercel / vercel/next.js

next/form does not normalize newlines in GET submissions after hydration

Open
#98,405 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Form (next/form)
Dominant language
JavaScript
Stars
142k
Forks
32.4k
Avg merge
2d 14h
Merged PRs (30d)
351

Description

Link to the code that reproduces this issue

https://github.com/Tnalxmsk/next-form-newline-repro

To Reproduce
  1. Clone the linked repository and open its directory.
  2. Run npm ci, then npm run build, followed by npm run start.
  3. Open http://localhost:3000/newline and wait for Hydrated: true.
  4. Leave the textarea unchanged and click Submit native. Inspect serverSearch.text on the result page.
  5. Return to /newline, wait for Hydrated: true, and click Submit next without changing the textarea.
  6. 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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with packages/next/src/client/form-shared.tsx at the FormData-to-URLSearchParams implementation, then run the linked reproduction using the documented npm commands. Done means hydrated string-action next/form GET submissions normalize textarea line endings to CRLF like native forms, while preserving single-line values.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, nextjs, react
Domain
frontend, web-dev
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
74/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.