automerge / automerge-classic

A JSON-like data structure (a CRDT) that can be modified concurrently by different users, and merged again automatically.
http://automerge.org/
MIT License
14.75k stars 466 forks source link

Serialized document won't load: "Columns must be in ascending order" #358

Closed skokenes closed 3 years ago

skokenes commented 3 years ago

Problem

I have a serialized document that won't load in AM 1.0.1. When I try to load it, I get the error message:

RangeError: Columns must be in ascending order
    at decodeColumnInfo (/sandbox/node_modules/automerge/dist/automerge.js:1415:41)
    at decodeDocumentHeader (/sandbox/node_modules/automerge/dist/automerge.js:2385:20)
    at decodeDocument (/sandbox/node_modules/automerge/dist/automerge.js:2408:31)
    at decodeChanges (/sandbox/node_modules/automerge/dist/automerge.js:1768:38)
    at Object.load (/sandbox/node_modules/automerge/dist/automerge.js:343:25)

Details

Working with automerge@1.0.1-preview0.

I have two peers connected to a webserver with a websocket, syncing a doc via the server as a middleman. The WebSockets do not use binary data, so I base64 encode the messages in the browser before sending, and then decode them to uint8 arrays on the server before applying the messages, and vice versa.

I also serialize the latest document and encode in base64 before storing as a string in a database.

After a co-editing session, occassionally I am no longer able to load the document that was serialized. Here is a codesandbox showing the behavior in NodeJS https://codesandbox.io/s/am-doc-wont-load-n3htd

Here is some sample code you can run yourself with a document that was generated and now won't load:

const { load } = require("automerge");

const b64ToUint8 = (b64) => Uint8Array.from(Buffer.from(b64, "base64"));
const serializedDocB64 =
  "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";

const binaryDoc = b64ToUint8(serializedDocB64);

// This throws the RangeError: Columns must be in ascending order
const doc = load(binaryDoc);

Any thoughts on what is going on here?

ept commented 3 years ago

Thank you for this helpful bug report. I've put a fix up here: #359