nextjs - 💡(How to fix) Fix App Router ISR emits invalid x-next-cache-tags header for non-ASCII dynamic pathnames [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#92145Fetched 2026-04-08 01:56:49
View on GitHub
Comments
1
Participants
2
Timeline
5
Reactions
0
Author
Timeline (top)
closed ×1commented ×1labeled ×1locked ×1

Error Message

TypeError: Invalid character in header content ["x-next-cache-tags"] at async handler (___next_launcher.cjs:209:7) at async Server.r (../../opt/rust/nodejs.js:2:15572) at async Server.<anonymous> (../../opt/rust/nodejs.js:17:10190) { code: 'ERR_INVALID_CHAR' }

Fix Action

Fix / Workaround

Current workaround on my side is to switch the route from ISR to SSR (dynamic = "force-dynamic"), which avoids x-next-cache-tags generation for that page.

Code Example

TypeError: Invalid character in header content ["x-next-cache-tags"]
    at async handler (___next_launcher.cjs:209:7)
    at async Server.r (../../opt/rust/nodejs.js:2:15572)
    at async Server.<anonymous> (../../opt/rust/nodejs.js:17:10190) {
  code: 'ERR_INVALID_CHAR'
}

---

Operating System:
  Platform: darwin
  Arch: arm64
Binaries:
  Node: 24.14.1
Relevant Packages:
  next: 16.2.1
  react: 18.3.1
  react-dom: 18.3.1

---

/products/15_톱사슴벌레-유충

---

_N_T_/products/15_톱사슴벌레-유충
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

I can provide a minimal reproduction if needed, but the issue is reproducible in an App Router dynamic page with all of the following:

  • a dynamic route such as app/products/[id]/page.tsx
  • generateStaticParams()
  • export const revalidate = 60
  • a dynamic param whose pathname contains non-ASCII characters, for example Korean slug text

To Reproduce

  1. Create an App Router dynamic route such as app/products/[id]/page.tsx
  2. Add generateStaticParams() and export const revalidate = 60
  3. Return a route param like 15_톱사슴벌레-유충
  4. Visit /products/15_%ED%86%B1%EC%82%AC%EC%8A%B4%EB%B2%8C%EB%A0%88-%EC%9C%A0%EC%B6%A9
  5. Observe the server/runtime error below

Current vs. Expected behavior

Current:

Next.js throws:

TypeError: Invalid character in header content ["x-next-cache-tags"]
    at async handler (___next_launcher.cjs:209:7)
    at async Server.r (../../opt/rust/nodejs.js:2:15572)
    at async Server.<anonymous> (../../opt/rust/nodejs.js:17:10190) {
  code: 'ERR_INVALID_CHAR'
}

Expected:

Next.js should not emit invalid header content for implicit cache tags when the resolved pathname contains non-ASCII characters.

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
Binaries:
  Node: 24.14.1
Relevant Packages:
  next: 16.2.1
  react: 18.3.1
  react-dom: 18.3.1

Which area(s) are affected? (Select all that apply)

App Router, Caching / Revalidation, Prerendering / ISR

Which stage(s) are affected? (Select all that apply)

next build, deployed app, production runtime

Additional context

This appears to be related to how implicit cache tags are generated for app pages.

From the current source:

  • resolvedPathname is used for implicit tags
  • that pathname is explicitly decoded and has trailing slash removed before being stored
  • the implicit tags are then written into the x-next-cache-tags header

The problem is that a decoded pathname such as:

/products/15_톱사슴벌레-유충

becomes an implicit tag like:

_N_T_/products/15_톱사슴벌레-유충

and this is not a valid Node.js header value, which triggers ERR_INVALID_CHAR.

So this is not just a URL-encoding problem. Even if the request URL is percent-encoded, the internal tag generation path uses the decoded pathname, and that decoded string is later serialized into a header.

A related recent change seems to be PR #88623, which mentions using resolvedPathname for implicit/soft tags in the x-next-cache-tags header.

From local validation:

  • _N_T_/products/15_%ED%86%B1%EC%82%AC%EC%8A%B4%EB%B2%8C%EB%A0%88-%EC%9C%A0%EC%B6%A9 is accepted as a Node header value
  • _N_T_/products/15_톱사슴벌레-유충 throws ERR_INVALID_CHAR
  • trailing slash does not help

Current workaround on my side is to switch the route from ISR to SSR (dynamic = "force-dynamic"), which avoids x-next-cache-tags generation for that page.

A possible fix direction would be:

  • keep decoded/normalized path semantics internally for matching and revalidation
  • but serialize header-safe ASCII values for x-next-cache-tags instead of raw decoded non-ASCII pathnames

extent analysis

TL;DR

The issue can be fixed by modifying the implicit cache tag generation to use URL-encoded pathnames instead of decoded ones.

Guidance

  • Verify that the issue is caused by non-ASCII characters in the pathname by testing with ASCII-only slugs.
  • Consider using a workaround by switching the route from ISR to SSR (dynamic = "force-dynamic") to avoid x-next-cache-tags generation.
  • Investigate modifying the x-next-cache-tags header generation to use URL-encoded pathnames, such as using encodeURIComponent on the resolvedPathname.
  • Test the fix by checking that the x-next-cache-tags header is correctly generated and does not throw ERR_INVALID_CHAR errors.

Example

// Example of how to URL-encode the pathname
const encodedPathname = encodeURIComponent(resolvedPathname);
// Use encodedPathname to generate the x-next-cache-tags header

Notes

  • This issue is specific to Next.js version 16.2.1 and may not apply to other versions.
  • The fix may require modifying the Next.js source code or waiting for an official patch.

Recommendation

Apply a workaround by switching the route from ISR to SSR (dynamic = "force-dynamic"), as this avoids the x-next-cache-tags generation and resolves the issue temporarily, until a more permanent fix can be implemented.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING