GrapesJS/grapesjs · error

Cannot remove a layer model from another layer model

Error message

Cannot remove a layer model from another layer model

What it means

LayerNode.removeChildAt removes the child at an index via this.model.at(index)/remove(...), which only works when the wrapped model is a Layers collection. If the node wraps a single Layer, the library throws this error because a Layer is a leaf, not a container.

Source

Thrown at packages/core/src/utils/sorter/LayerNode.ts:63

   */
  addChildAt(node: LayerNode, index: number) {
    if (this.model instanceof Layer) {
      throw Error('Cannot add a layer model to another layer model');
    }

    const newModel = this.model.add(node.model, { at: index });
    return new LayerNode(newModel);
  }

  /**
   * Remove a child LayerNode at a specified index in the Layers model.
   * @param index - The index of the child to remove.
   * @returns The removed LayerNode.
   * @throws Error if trying to remove from a Layer (not a Layers).
   */
  removeChildAt(index: number) {
    if (this.model instanceof Layer) {
      throw Error('Cannot remove a layer model from another layer model');
    }

    const child = this.model.at(index);
    if (child) {
      this.model.remove(child);
    }
  }

  /**
   * Get the index of a child LayerNode in the current Layers model.
   * @param node - The child LayerNode to find.
   * @returns The index of the child, or -1 if not found.
   */
  indexOfChild(node: LayerNode): number {
    if (!(node.model instanceof Layer) || !(this.model instanceof Layers)) {
      return -1;
    }
    return this.model.indexOf(node.model);

View on GitHub (pinned to 2bdeda85b8)

Solutions

  1. Call removeChildAt on the node's parent (node.getParent()) rather than on the Layer node itself
  2. Guard with `node.model instanceof Layers` before calling removeChildAt
  3. Use the model API directly on the collection: `layersCollection.remove(layer)` when you already hold both references

Example fix

// before
selectedNode.removeChildAt(index); // selectedNode is a leaf Layer
// after
const parent = selectedNode.getParent();
if (parent) {
  parent.removeChildAt(parent.indexOfChild(selectedNode));
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(node.model instanceof Layers)) {
  throw new Error('removeChildAt requires a Layers collection node');
}

Type guard

function isLayersNode(n: LayerNode): n is LayerNode & { model: Layers } {
  return n.model instanceof Layers;
}

Try / catch

try {
  node.removeChildAt(index);
} catch (e) {
  if (e.message.includes('Cannot remove a layer model')) {
    // retry on the parent collection instead
  }
}

Prevention

When it happens

Trigger: Calling removeChildAt(index) on a LayerNode whose model is a Layer instead of a Layers collection — e.g. deleting a sub-layer by resolving the wrong tree level, or calling removeChildAt on the leaf node itself rather than its parent (getParent()).

Common situations: Custom layer-management UIs implementing delete on the selected node instead of its parent collection; recursive tree-removal code that assumes uniform nesting depth; code ported from ComponentNode sorting where children exist at more levels.

Related errors


AI-assisted analysis of GrapesJS/grapesjs@2bdeda85b8 (2026-08-30). Data as JSON: /api/errors/fd18e2b20fe27abc. Report an issue: GitHub.