nextjs - 💡(How to fix) Fix Malformed html causes "Connection closed." error without clear stack trace [1 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#84694Fetched 2026-04-08 02:18:44
View on GitHub
Comments
0
Participants
1
Timeline
3
Reactions
3
Participants
Timeline (top)
issue_type_added ×1labeled ×1subscribed ×1

Error Message

In our big production app, I do not get a 418 Hydration Failed error, only "Connection closed.", which makes it even more confusing. I just commented out components until the app started working again.

Code Example

import { Suspense } from "react";

const MALFORMED_HTML = `<p>Hello, world!</p`;

const getHtmlPromise = async (n: number) => {
  await new Promise((resolve) => setTimeout(resolve, 1000 * n));
  return MALFORMED_HTML;
}

export default async function Home() {
  const content = {
    one: getHtmlPromise(1),
    two: getHtmlPromise(2),
  }  

  return (
    <div>
      <Inner promise={content.one} />
      <Suspense fallback={<div>Loading...</div>}>
        <Inner promise={content.two} />
      </Suspense>
    </div>
  );
}

async function Inner({ promise }: { promise: Promise<string> }) {
  return <div dangerouslySetInnerHTML={{ __html: await promise }} />
}

---

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.0.0: Mon Aug 25 21:17:51 PDT 2025; root:xnu-12377.1.9~3/RELEASE_ARM64_T6000
  Available memory (MB): 32768
  Available CPU cores: 10
Binaries:
  Node: 20.14.0
  npm: 10.7.0
  Yarn: 4.3.0
  pnpm: 10.4.1
Relevant Packages:
  next: 15.5.4 // Latest available version is detected (15.5.4).
  eslint-config-next: N/A
  react: 19.2.0
  react-dom: 19.2.0
  typescript: N/A
Next.js Config:
  output: N/A
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

https://github.com/hansottowirtz/connection-closed-repro

To Reproduce

Deployed

https://connection-closed-repro.vercel.app

Local

  1. Start the app with pnpm dev
  2. Navigate to the app, it will immediately crash

Current vs. Expected behavior

This is all that's needed to crash a Next.js app in a cryptic way ("Connection closed."). It doesn't provide any usable stack trace or component source. It only happens when using Suspense in some way.

In our big production app, I do not get a 418 Hydration Failed error, only "Connection closed.", which makes it even more confusing. I just commented out components until the app started working again.

import { Suspense } from "react";

const MALFORMED_HTML = `<p>Hello, world!</p`;

const getHtmlPromise = async (n: number) => {
  await new Promise((resolve) => setTimeout(resolve, 1000 * n));
  return MALFORMED_HTML;
}

export default async function Home() {
  const content = {
    one: getHtmlPromise(1),
    two: getHtmlPromise(2),
  }  

  return (
    <div>
      <Inner promise={content.one} />
      <Suspense fallback={<div>Loading...</div>}>
        <Inner promise={content.two} />
      </Suspense>
    </div>
  );
}

async function Inner({ promise }: { promise: Promise<string> }) {
  return <div dangerouslySetInnerHTML={{ __html: await promise }} />
}

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.0.0: Mon Aug 25 21:17:51 PDT 2025; root:xnu-12377.1.9~3/RELEASE_ARM64_T6000
  Available memory (MB): 32768
  Available CPU cores: 10
Binaries:
  Node: 20.14.0
  npm: 10.7.0
  Yarn: 4.3.0
  pnpm: 10.4.1
Relevant Packages:
  next: 15.5.4 // Latest available version is detected (15.5.4).
  eslint-config-next: N/A
  react: 19.2.0
  react-dom: 19.2.0
  typescript: N/A
Next.js Config:
  output: N/A

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

React

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

Vercel (Deployed), next dev (local)

Additional context

No response

extent analysis

TL;DR

The issue is likely caused by the malformed HTML returned by the getHtmlPromise function, which is then used in the dangerouslySetInnerHTML attribute, and can be fixed by ensuring the HTML is properly formatted.

Guidance

  • Verify that the HTML returned by getHtmlPromise is properly formatted by logging it to the console or using a debugger.
  • Check the MALFORMED_HTML constant for any syntax errors, and correct them if necessary.
  • Consider using a library or function to sanitize the HTML before using it in dangerouslySetInnerHTML to prevent similar issues in the future.
  • Test the application with a properly formatted HTML string to confirm that the issue is resolved.

Example

const WELL_FORMED_HTML = `<p>Hello, world!</p>`; // note the closing tag

Notes

The provided code snippet is a minimal reproducible example, but the actual issue may be more complex in the production application. Ensuring proper HTML formatting and sanitization can help prevent similar issues.

Recommendation

Apply workaround: Ensure that all HTML used in dangerouslySetInnerHTML is properly formatted and sanitized to prevent connection closed errors.

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