{"record":{"id":"44d22c51eacc6a12","repo":"emberjs/ember.js","slug":"rehydration-with-nextsibling-not-supported","errorCode":null,"errorMessage":"Rehydration with nextSibling not supported","messagePattern":"Rehydration with nextSibling not supported","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@glimmer/runtime/lib/vm/rehydrate-builder.ts","lineNumber":51,"sourceCode":"  constructor(\n    element: SimpleElement,\n    nextSibling: Nullable<SimpleNode>,\n    public readonly startingBlockDepth: number\n  ) {\n    super(element, nextSibling);\n    this.openBlockDepth = startingBlockDepth - 1;\n  }\n}\n\nexport class RehydrateTree extends NewTreeBuilder implements TreeBuilder {\n  private unmatchedAttributes: Nullable<SimpleAttr[]> = null;\n  declare cursors: Stack<RehydratingCursor>; // Hides property on base class\n  blockDepth = 0;\n  startingBlockOffset: number;\n\n  constructor(env: Environment, parentNode: SimpleElement, nextSibling: Nullable<SimpleNode>) {\n    super(env, parentNode, nextSibling);\n    if (nextSibling) throw new Error('Rehydration with nextSibling not supported');\n\n    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- @fixme\n    let node = this.currentCursor!.element.firstChild;\n\n    while (node !== null) {\n      if (isOpenBlock(node)) {\n        break;\n      }\n      node = node.nextSibling;\n    }\n\n    assert(node, 'Must have opening comment for rehydration.');\n    this.candidate = node;\n    const startingBlockOffset = getBlockDepth(node);\n    if (startingBlockOffset !== 0) {\n      // We are rehydrating from a partial tree and not the root component\n      // We need to add an extra block before the first block to rehydrate correctly\n      // The extra block is needed since the renderComponent API creates a synthetic component invocation which generates the extra block","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/emberjs/ember.js/blob/26f97246a8bf2e28edf26ac3093da2e86c04ffc5/packages/@glimmer/runtime/lib/vm/rehydrate-builder.ts#L33-L69","documentation":"The rehydration builder can only replay server-rendered HTML by walking the existing children of the parent element; it has no support for starting mid-stream at a specific sibling. The RehydrateBuilder constructor throws immediately if a non-null nextSibling cursor is supplied.","triggerScenarios":"Constructing `new RehydrateBuilder(env, parentNode, nextSibling)` with a non-null nextSibling — i.e. attempting to serialize/rehydrate into a cursor that points at an insertion point between existing nodes.","commonSituations":"Embedding Glimmer SSR/rehydration into a custom host framework that uses element cursors with siblings; using Glimmer's client-side builder APIs against a rehydrating element with an anchor node.","solutions":["Pass `null` as nextSibling when creating the rehydrating builder.","If you must append relative to a sibling, clear or restructure the parent element so rehydration starts from the first child.","Use the non-rehydrating element builder for insertion at a specific sibling position instead of RehydrateBuilder."],"exampleFix":"// before\nlet builder = new RehydrateBuilder(env, rootElement, anchorNode);\n\n// after\nlet builder = new RehydrateBuilder(env, rootElement, null);","handlingStrategy":"validation","validationCode":"if (nextSibling != null) {\n  throw new Error('RehydrateBuilder requires nextSibling === null');\n}\nconst builder = new RehydrateBuilder(env, parentNode, null);","typeGuard":"function canRehydrate(cursor) {\n  return cursor.nextSibling == null;\n}","tryCatchPattern":null,"preventionTips":["Always pass null as nextSibling to RehydrateBuilder.","Use the regular element builder when you need sibling-anchored insertion.","Document rehydration constraints in any custom SSR host integration.","Add an early assertion in your bootstrapping code around builder construction."],"tags":["glimmer","ssr","rehydration","unsupported-feature"],"backgroundTag":"rehydration-unsupported-cursor","analyzedSha":"26f97246a8bf2e28edf26ac3093da2e86c04ffc5","analyzedAt":"2026-09-01T05:01:28.182Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}