{"record":{"id":"1ed0e17dd32a36d2","repo":"preactjs/preact","slug":"undefined-parent-passed-to-render-this-is-the-s","errorCode":null,"errorMessage":"Undefined parent passed to render(), this is the second argument.\nCheck if the element is available in the DOM/has the correct id.","messagePattern":"Undefined parent passed to render\\(\\), this is the second argument\\.\nCheck if the element is available in the DOM/has the correct id\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"debug/src/debug.js","lineNumber":115,"sourceCode":"\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\terrorInfo = errorInfo || {};\n\t\terrorInfo.componentStack = getOwnerStack(vnode);\n\t\toldCatchError(error, vnode, oldVNode, errorInfo);\n\n\t\t// when an error was handled by an ErrorBoundary we still log it, matching what\n\t\t// React does in development. Errors that were not handled are rethrown by the\n\t\t// core and thus surface as regular uncaught errors.\n\t\tif (typeof error.then != 'function') {\n\t\t\tconsole.error(error);\n\t\t}\n\t};\n\n\toptions._root = (vnode, parentNode) => {\n\t\tif (!parentNode) {\n\t\t\tthrow new Error(\n\t\t\t\t'Undefined parent passed to render(), this is the second argument.\\n' +\n\t\t\t\t\t'Check if the element is available in the DOM/has the correct id.'\n\t\t\t);\n\t\t}\n\n\t\tlet isValid;\n\t\tswitch (parentNode.nodeType) {\n\t\t\tcase ELEMENT_NODE:\n\t\t\tcase DOCUMENT_FRAGMENT_NODE:\n\t\t\tcase DOCUMENT_NODE:\n\t\t\t\tisValid = true;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tisValid = false;\n\t\t}\n\n\t\tif (!isValid) {\n\t\t\tlet componentName = getDisplayName(vnode);","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/preactjs/preact/blob/e881e7e8386d7a430f87498a41c6a532992b4599/debug/src/debug.js#L97-L133","documentation":"Thrown by Preact's debug build from the options._root hook when the parentNode passed as the second argument to render() is falsy (undefined/null). The debug layer guards the mount target because rendering into nothing cannot attach a DOM tree and would silently fail. It fires before the core renderer runs (oldRoot is called after the check).","triggerScenarios":"Calling render(<App/>, document.getElementById('does-not-exist')) when no element with that id exists; calling render() before the target node is parsed (script in <head> without defer); passing a variable that was never assigned as the second arg; SSR/Node environments where document is absent so the lookup returns undefined.","commonSituations":"Script tag placed in <head> before the DOM body is built; typo in the container id; bundler/DOM-timing race where the entry script runs before the mount node exists; migrating from React 17 createRoot which auto-defers vs Preact's synchronous render; Jest/RTL tests that forget to append a container to document.body.","solutions":["Verify the container exists: open DevTools and run document.getElementById('app') — it must return an Element, not null.","Move the entry script to the end of <body> or add the defer attribute so the DOM is parsed first.","Guard the call: const root = document.getElementById('app'); if (root) render(<App/>, root);","Check for typos in the id and that the id attribute is actually written in the served HTML, not just a template that failed to render server-side."],"exampleFix":"// before\nimport { render } from 'preact';\nrender(<App />, document.getElementById('app'));\n\n// after\nimport { render } from 'preact';\nconst root = document.getElementById('app');\nif (!root) throw new Error('Mount node #app not found in DOM');\nrender(<App />, root);","handlingStrategy":"validation","validationCode":"import { ELEMENT_NODE, DOCUMENT_NODE, DOCUMENT_FRAGMENT_NODE } from './constants';\n\nfunction assertMountNode(node, id) {\n  if (!node) {\n    throw new Error(`Mount node \"${id}\" not found. Ensure the DOM is ready and the id is correct.`);\n  }\n  const allowed = new Set([ELEMENT_NODE, DOCUMENT_NODE, DOCUMENT_FRAGMENT_NODE]);\n  if (!allowed.has(node.nodeType)) {\n    throw new Error(`Mount node \"${id}\" has invalid nodeType ${node.nodeType}.`);\n  }\n  return node;\n}\n\n// usage\nconst root = assertMountNode(document.getElementById('app'), 'app');\nrender(<App />, root);","typeGuard":"// node is guaranteed by caller\nfunction isMountableNode(node) {\n  return node != null && [1, 9, 11].includes(node.nodeType);\n}\n// runtime: if (isMountableNode(el)) render(<App/>, el);","tryCatchPattern":null,"preventionTips":["Place the entry <script> at the end of <body> or use the defer attribute.","Always resolve the mount node into a variable and log it before render during onboarding.","In tests, append a fresh container to document.body in beforeEach."],"tags":["preact","render","dom","mount","debug-build"],"backgroundTag":null,"analyzedSha":"e881e7e8386d7a430f87498a41c6a532992b4599","analyzedAt":"2026-08-13T04:27:04.532Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}