Handling unknown nodes/marks in prosemirror schema

Is there a recommended way to handle unknown nodes/marks with y-prosemirror? E.g. if an older client loads a document with a newer schema.

As I understand, Prosemirror will just throw away any content that doesn’t confirm to the schema, and that behavior is not configurable.

y-prosemirror doesn’t seem to be schema-aware, so I’m assuming there’s no way it could circumvent that by detecting the drift itself. Is that the case?

y-prosemirror doesn’t transform documents for older schemas. Although it would be nice if it could do that.

For now, I recommend that you handle schemas yourself. If the editor notices that the document uses schema version x, but it only understands x-1, then it shouldn’t open the document.

y-prosemirror is actually schema-aware. It removes invalid nodes, that don’t conform to your schema (this is necessary even without editors having different schemas. Invalid nodes could be the result of concurrent actions.). So I suggest that you don’t even open the document, if your editor doesn’t understand the schema.

Also, I suggest only “extending” the editor schema. Don’t remove features, as it wouldn’t allow newer releases to open old document.

The strategy of refusing to open the document wouldn’t cover the case where a client with a newer schema joins a document concurrently with a client with an older schema right?

Imagine the following scenario:

  • client 1, which knows node type X and Y opens the doc
  • new version of the application is released with node types X, Y and Z
  • client 2, running the new version, opens the document and starts syncing with client 1
  • client 2 adds a node of type Z
  • client 1 doesn’t know how to handle Z

If I understand correctly there’s no good way to handle this scenario today, but please correct me if I’m wrong.

One potential solution would be to map such unsupported nodes to a generic “unknown” node type that acts as a passthrough and leaves the content untouched, but I have no idea how complex that would be to implement in y-prosemirror.

You could probably add your own versioning by setting a “version” value to the doc with eg Y.Map. Then just forcing a reload if they mismatch against the current schema. Not sure though would client 1 override client 2 changes by throwing them out before the reload could happen.

But you should probably have some kind of migration functionality in place anyway incase you had to make breaking changes to your schema. Sometimes it’s unavoidable. I think blocksuite editor has implemented one in their toolkit for Yjs.

In general though you should have some mechanism in place to notify users of outdated client versions. Similarly your whole app could break if you make a breaking change to an API endpoint and users have outdated clients so this isn’t just Yjs problem.

1 Like

This feature is currently not planned. It was planned for the y-prosemirror rewrite, but I couldn’t find the funding for it. Maybe next year.