TypeError: Cannot read properties of undefined (reading 'type') when Inserting Nodes with a ReplaceStep

I’m trying to write a command which dispatches the transaction to insert multiple ImageBlock Node from files with a single ReplaceStep, but keep running into an error. Could anyone help me figure out what I’m doing wrong…?

To give a little more context, the error only happens when I’m trying to insert the ‘imageBlock’ node and doesn’t with a normal paragraph… When I try inserting with tr.insert then it works, but I’m creating ReplaceStep in order to combine the changes in a single step.

Schema of the ImageBlock Node:

{
  group: 'block',
  attrs: {
    src: {},
    alt: { default: null },
  },
  atom: true,
  toDOM: (node) => {
    const { src, alt } = node.attrs;
    return [ //the image will be wrapped with div <div><img /></div>
      'div',
      {
        class: 'noteImageBlock',
        'data-src': src,
        'data-alt': alt,
      },
      [
        'img',
        { src, alt, },
      ],
    ];
  },
}

The Trigger(which is an input change event in React)

  const uploadImages = (e: React.ChangeEvent<HTMLInputElement>, editorView: EditorView) => {
    const files = e.target.files;

    createImageBlocks(files)(editorView.state, editorView.dispatch);
    editorView.focus();
  };

The Command

const createImageBlocks = (files: File[]): Command => {
  return (state: EditorState, dispatch?: (tr: Transaction) => void) => {
    if (!dispatch) return false;

    const { tr, selection, doc } = state;
    const { empty, head } = selection;
    if (!empty) return false;

    const resolvedHead = doc.resolve(head);
    const insertingPosition =
      head + (resolvedHead.parent.nodeSize - resolvedHead.parentOffset);

    const nodes = files.map((file) => {
      const localUrl = window.URL.createObjectURL(file);

      return Node.fromJSON(SCHEMA, {
        type: 'imageBlock',
        attrs: {
          src: localUrl,
          alt: file.name.replace(/\.[^/.]+$/, ''),
        },
      });
    });

    const slice = new Slice(Fragment.from(nodes), 1, 1);
    dispatch(
      tr.step(
        new ReplaceStep(insertingPosition, insertingPosition, slice, true),
      ),
    );
    return true;
  };
};

The Error

Uncaught TypeError: Cannot read properties of undefined (reading 'type')
    at checkJoin (index.js:717:1)
    at joinable (index.js:722:1)
    at replaceThreeWay (index.js:756:1)
    at replaceOuter (index.js:713:1)
    at replace (index.js:696:1)
    at Node.replace (index.js:1320:1)
    at StepResult.fromReplace (index.js:409:1)
    at ReplaceStep.apply (index.js:705:1)
    at Transaction.maybeStep (index.js:1793:1)
    at Transaction.step (index.js:1783:1)

I can’t reproduce precisely this error, but your position computation looks very dodgy

You’re taking the cursor position plus the size of the parent node minus the offset of that position into this parent node. You may be trying to compute selection.$head.end() without accounting for opening/closing token size?

Thank you for the reply! That’s a really neat way to handle position!

But still no luck with the error…

It looks like that has something to do with the lack of a type compatibility with replacing block with the current block…

I’ll try and look further, but if I couldn’t figure out then I will just use tr.insert