Error "Cannot read properties of undefined (reading 'localsInner')" when working with DecorationSet

Hello! Help me, please! The project I’m working on has a block for working with code and diagrams. For this block, I created a widget that manages its attributes. The block and widget look something like this:

decorations.push(
  Decoration.widget(
    pos,
    (_view, getPos) => renderer.getContainer(getPos(), node, editor),
    {
      renderer,
      side: -10,
      forId: node.attrs.id,
      ignoreSelection: true,
      destroy: () => {
        // Widget unmount code here...
      },
    },
  ),
);

I render the widget content using react:

getContainer = (pos: number, node: ProsemirrorNode, editor: Editor) => {
    this.root.render(
      <ControlWidget
        pos={pos}
        node={node}
        editor={editor}
      />,
    );
    return this.container;
  };

When the user interacts with the widget, I send transactions to change the node attributes. Like this:

const handleLanguage = useCallback((value: string) => {
    const dispatch = editor.view.dispatch;
    const tr = editor.view.state.tr;
    dispatch(
      tr
        .setNodeAttribute(pos, 'language', value)
        .setNodeAttribute(pos, 'mermaidMode', MERMAID_MODE.CODE_AND_DIAGRAM)
    );
...

And it works well in most cases. But if my node is at the very beginning of the document (at position 0) or two such nodes in the document follow each other immediately, then problems begin. When attempting to perform any transaction to change attributes, the following error occurs:

The version of prosemirror-view I’m using is 1.33.1 I also read this: Decoration issue when having multiple custom Plugins - #7 by TeemuKoivisto But the advice from there didn’t work in my case. Help…

1 Like

What does your decorations prop, as passed to ProseMirror, look like?

The code looks something like this:

return new Plugin({
  key: new PluginKey('codeBlockControl'),
  state: {
    init: () => {
      return DecorationSet.empty;
    },
    apply: (tr, decorationSet, oldState, newState) => {
      const decorations: Decoration[] = [];

       // Here I iterate over the nodes and create widgets in the positions I need (just before the nodes)...       

      return DecorationSet.create(tr.doc, decorations);
    },
  },
  props: {
    decorations(state) {
      return this.getState(state);
    },
  },
});

That looks correct. The stack trace includes a finishTransaction function, but there’s no such function in the ProseMirror library. Is this your own custom code? Could it be that the issue is in there?

Sorry for not attaching the full trace. Here it is:

We apply the function finishTransaction inside the function dispatchTransaction.

dispatchTransaction: function (transaction) {
  const { state, transactions } = this.state.applyTransaction(transaction);
        
  const finishTransaction = () => {
    this.updateState(state);
    // Here we notify other components of the application that changes have occurred in the editor.
  };
   
   // Here we collect statistical information. For example, the number of blocks in the old and new states

  finishTransaction();
},

I see. Then I’m not sure what the problem is. You’re going to have to try and reduce the crash to a minimal program. (I doubt the React stuff is relevant, and the dispatch hook also seems correct enough. Just keep removing pieces that aren’t necessary to reproduce the problem, and see what you end up with.)

After many attempts, we managed to come to this decision:

It’s strange that such a technique had to be used to change attributes…