The
next/ogpackage makes it straightforward to generate dynamic Open Graph images, Twitter cards, and blog thumbnails using JSX and CSS in Next.js. One of the most frustrating errors you can run into, though, is a seemingly random HTTP 502 response when requesting a generated image. The browser shows nothing useful, and there is no obvious indication of what went wrong.The real cause is almost always a layout constraint specific to the
next/ogrendering engine, and the fix takes seconds once you know what to look for.What this covers:
Why
next/ogreturns an HTTP 502 errorWhat "Expected
<div>to have explicitdisplay: flex" meansHow to fix the issue correctly
Common layout mistakes and how to avoid them
Why the HTTP 502 Error Happens
Unlike traditional React components rendered in the browser, next/og uses a specialized rendering engine to convert JSX into a static image. This renderer supports only a subset of HTML and CSS and enforces stricter layout rules than a normal browser would.
When the renderer encounters an unsupported layout, image generation fails entirely. Instead of surfacing a descriptive error in the browser, Next.js returns a generic HTTP 502 Bad Gateway response. The actual error message ends up in your terminal logs:
Error: failed to pipe response
Expected <div> to have explicit "display: flex" or "display: none" if it has more than one child node.That log line is the real cause of the problem.
Understanding the Error
The key part of the message is:
Expected <div> to have explicit "display: flex" or "display: none"In next/og, every <div> containing more than one direct child must explicitly declare its display behavior. A component like this will fail:
<div>
<h1>Hello World</h1>
<p>Generated with next/og</p>
</div>Browsers render a <div> as display: block by default, but the next/og renderer makes no such assumption. It requires you to be explicit.
The Fix
Add display: 'flex' to any <div> that has two or more child elements:
<div
style={{
display: 'flex',
}}
>
<h1>Hello World</h1>
<p>Generated with next/og</p>
</div>If you want the children stacked vertically, which is the more common case, also set flexDirection:
<div
style={{
display: 'flex',
flexDirection: 'column',
}}
>
<h1>Hello World</h1>
<p>Generated with next/og</p>
</div>This satisfies the renderer and resolves the 502 error.
Why flexDirection Matters
A common follow-up mistake is adding only display: 'flex' and stopping there. Flexbox defaults to a horizontal row layout, so your elements will appear side by side:
Title DescriptionAdding flexDirection: 'column' stacks them vertically as you would normally expect:
Title
DescriptionIn most Open Graph image layouts, vertical stacking is what you want, so it is worth making this a habit whenever you reach for display: 'flex' in next/og.
Check Every Parent <div>, Not Just the Root
The error is not always caused by the outermost container. Consider this example:
<div style={{ display: 'flex', flexDirection: 'column' }}>
<div>
<h1>Title</h1>
<p>Description</p>
</div>
<footer>Footer</footer>
</div>The root container is correct, but the nested <div> still has two children with no explicit display. The renderer will throw the same error regardless of how deep in the tree the violation occurs.
The fix is to apply the style to every <div> with multiple children:
<div style={{ display: 'flex', flexDirection: 'column' }}>
<div style={{ display: 'flex', flexDirection: 'column' }}>
<h1>Title</h1>
<p>Description</p>
</div>
<footer>Footer</footer>
</div>When debugging this error, work through every parent <div> in your JSX rather than assuming the root element is the only place to check.
Other Layout Rules to Keep in Mind
The display: flex requirement is the most common issue, but next/og supports a more limited set of CSS features than a modern browser does. A few other things worth knowing:
Prefer Flexbox over CSS Grid. Grid support in
next/ogis limited.Define layout styles explicitly instead of relying on any browser defaults.
Keep nesting reasonably shallow. Complex deeply nested layouts are harder to debug and more likely to hit unsupported behavior.
Test image generation locally before deploying to catch rendering errors early.
Straightforward Flexbox containers with explicit styles produce the most reliable results.
Frequently Asked Questions
Why does the browser only show HTTP 502 and not the real error?
The browser only receives the failed image response. The rendering error is written to your terminal or server logs, so that is where you need to look when diagnosing next/og issues.
Can I use display: block instead of display: flex?
No. The renderer specifically requires containers with multiple children to use display: flex or display: none. Block display is not supported for multi-child elements.
Does every <div> need display: flex?
Only <div> elements with two or more direct child nodes require an explicit display value. Single-child containers are not affected.
Can I use normal HTML and CSS in next/og?
Mostly, but not entirely. The renderer supports a subset of HTML and CSS optimized for server-side image generation. Some browser-specific features and CSS properties are unavailable or behave differently from what you might expect.
Key Takeaways
A generic HTTP 502 from
next/ogalmost always hides a layout rendering error. Check your terminal logs for the real exception.Every
<div>with two or more direct children must explicitly setdisplay: 'flex'ordisplay: 'none'.Add
flexDirection: 'column'when you want children stacked vertically rather than side by side.Nested
<div>elements are just as likely to be the culprit as the root container. Audit the entire component tree.Prefer Flexbox over Grid, and define all layout styles explicitly rather than relying on defaults.
Conclusion
The "Expected <div> to have explicit display: flex" error is one of the most common stumbling blocks when working with next/og, largely because it surfaces as a generic HTTP 502 rather than a clear layout warning in the browser.
Once you know what to look for, the fix is quick: add display: 'flex' to every <div> with multiple children, set flexDirection: 'column' for vertical layouts, and check nested containers as well as the root element. In most cases, a single overlooked <div> is all it takes to prevent next/og from generating the image at all.
If you have run into other next/og layout quirks worth sharing, drop them in the comments.
What was the trickiest part of debugging your next/og setup?




