{"record":{"id":"8113de65e8c62a68","repo":"honojs/hono","slug":"async-component-is-not-supported-in-rendertostring","errorCode":null,"errorMessage":"Async component is not supported in renderToString","messagePattern":"Async component is not supported in renderToString","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/jsx/dom/server.ts","lineNumber":27,"sourceCode":"import version from './'\n\nexport interface RenderToStringOptions {\n  identifierPrefix?: string\n}\n\n/**\n * Render JSX element to string.\n * @param element JSX element to render.\n * @param options Options for rendering.\n * @returns Rendered string.\n */\nconst renderToString = (element: Child, options: RenderToStringOptions = {}): string => {\n  if (Object.keys(options).length > 0) {\n    console.warn('options are not supported yet')\n  }\n  const res = element?.toString() ?? ''\n  if (typeof res !== 'string') {\n    throw new Error('Async component is not supported in renderToString')\n  }\n  return res\n}\n\nexport interface RenderToReadableStreamOptions {\n  identifierPrefix?: string\n  namespaceURI?: string\n  nonce?: string\n  bootstrapScriptContent?: string\n  bootstrapScripts?: string[]\n  bootstrapModules?: string[]\n  progressiveChunkSize?: number\n  signal?: AbortSignal\n  onError?: (error: unknown) => string | void\n}\n\n/**\n * Render JSX element to readable stream.","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/honojs/hono/blob/e2740d5a1bd0b4254e517e3af8b60789284bc7bd/src/jsx/dom/server.ts#L9-L45","documentation":"hono/jsx/dom/server's renderToString calls element.toString(); if that returns a Promise (or other non-string), it means the element tree contains an async component or unawaited async expression, which synchronous string rendering cannot fulfill.","triggerScenarios":"Rendering a JSX tree that includes an async function component or an element whose toString resolves to a Promise, e.g. `renderToString(<AsyncPage />)` where AsyncPage is `async () => {...}`; passing a Promise child or memoized async fragment.","commonSituations":"Switching from hono's stream renderer (renderToReadableStream, which supports async) to renderToString without converting components; introducing data-fetching (await prisma..., await fetch...) into components used in the sync path; refactoring a page component to async during SSR setup.","solutions":["Use renderToReadableStream (or another async renderer) for trees containing async components","Make the component synchronous: await the data outside and pass it in as props","Replace async components in the sync tree with sync ones, or split async subtrees into the streaming path"],"exampleFix":"// before\nconst AsyncPage = async () => {\n  const data = await getData()\n  return <div>{data}</div>\n}\nconst html = renderToString(<AsyncPage />) // throws\n// after\nconst data = await getData()\nconst html = renderToString(<Page data={data} />)","handlingStrategy":"type-guard","validationCode":"const isSyncRenderable = (el: Child): boolean => {\n  const s = (el as { toString?: () => unknown })?.toString?.()\n  return typeof s === 'string'\n}","typeGuard":"const isAsyncComponent = (fn: unknown): boolean =>\n  typeof fn === 'function' && fn.constructor?.name === 'AsyncFunction'","tryCatchPattern":"null","preventionTips":["Use renderToReadableStream for any tree with async components","Fetch data before render and pass results as props in sync paths","Audit for async function components before switching to renderToString"],"tags":["hono","jsx","ssr","async","rendertostring"],"backgroundTag":"async-component-in-sync-render","analyzedSha":"e2740d5a1bd0b4254e517e3af8b60789284bc7bd","analyzedAt":"2026-08-28T10:18:08.750Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}