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.77k stars 467 forks source link

× "TypeError: Not a byte array: 133" error when userB receives data from userA. #507

Closed ikibkilam closed 1 year ago

ikibkilam commented 1 year ago

I keep getting "TypeError: Not a byte array: 133" error, when UserA sends data to UserB, via socketIO. The relevant code snippets and outputs are below.

Code


// UserA calls Automerge.getChanges(), base64 encodes Uint8Array using byte-base64 package, sends to server using socketio
   const handleChanges = () => {
       <Some Code>

       const changes = Automerge.getChanges(oldDoc, docRef.current);
       console.log('changes: ', changes);

       const byteBase64EncodedChanges0 = bytesToBase64(changes[0]);
       console.log('changes[0] encoded: ',  byteBase64EncodedChanges0);

       sendMsg(byteBase64EncodedChanges0, false, docRef.current.text.toString());
}

// UserB receives base64 encoded message from server, decodes to Uint8Array and calls Automerge.applyChanges()
   const receiveMsgs = (msg) => {
      console.log('received message: ', msg)

      const message = base64ToBytes(msg);
      console.log('decoded message: ', message);

      docRef.current = Automerge.applyChanges(docRef.current, message);
}

Output


changes:
[Uint8Array(109)]0: Uint8Array(109) [133, 111, 74, 131, 82, 121, 161, 109, 1, 99, 1, 22, 30, 226, 64, 128, 11, 206, 61, 54, 181, 161, 60, 32, 86, 178, 70, 151, 86, 145, 221, 56, 202, 118, 94, 175, 133, 236, 160, 175, 140, 194, 186, 16, 16, 2, 3, 7, 37, 82, 74, 212, 151, 181, 186, 79, 159, 98, 228, 157, 2, 38, 237, 253, 148, 152, 6, 0, 0, 10, 1, 2, 2, 2, 17, 2, 19, 2, 52, 1, 66, 2, 86, 2, 112, 2, 113, 2, 115, 2, 127, 0, 127, 1, 127, 0, 127, 35, 1, 127, …]length: 1[[Prototype]]: Array(0)

changes[0] encoded:  
hW9Kg1J5oW0BYwEWHuJAgAvOPTa1oTwgVrJGl1aR3TjKdl6vheygr4zCuhAQAgMHJVJK1Je1uk+fYuSdAibt/ZSYBgAACgECAgIRAhMCNAFCAlYCcAJxAnMCfwB/AX8AfyMBfwN/AH8BfwB/Iw==

received message:
hW9Kg1J5oW0BYwEWHuJAgAvOPTa1oTwgVrJGl1aR3TjKdl6vheygr4zCuhAQAgMHJVJK1Je1uk+fYuSdAibt/ZSYBgAACgECAgIRAhMCNAFCAlYCcAJxAnMCfwB/AX8AfyMBfwN/AH8BfwB/Iw==

decoded message:
Uint8Array(109) [133, 111, 74, 131, 82, 121, 161, 109, 1, 99, 1, 22, 30, 226, 64, 128, 11, 206, 61, 54, 181, 161, 60, 32, 86, 178, 70, 151, 86, 145, 221, 56, 202, 118, 94, 175, 133, 236, 160, 175, 140, 194, 186, 16, 16, 2, 3, 7, 37, 82, 74, 212, 151, 181, 186, 79, 159, 98, 228, 157, 2, 38, 237, 253, 148, 152, 6, 0, 0, 10, 1, 2, 2, 2, 17, 2, 19, 2, 52, 1, 66, 2, 86, 2, 112, 2, 113, 2, 115, 2, 127, 0, 127, 1, 127, 0, 127, 35, 1, 127, …][0 … 99][100 … 108]buffer: ArrayBuffer(111)

Crash Message


×
TypeError: Not a byte array: 133
new Decoder
C:/Users/bikim/source/VS Code/UamTs/client/node_modules/automerge/backend/encoding.js:296
  293 | class Decoder {
  294 |   constructor(buffer) {
  295 |     if (!(buffer instanceof Uint8Array)) {
> 296 |       throw new TypeError(`Not a byte array: ${buffer}`)
  297 |     }
  298 |     this.buf = buffer
  299 |     this.offset = 0

I thought maybe it was the base64 package I am using, so I used two other packages instead (base64-arraybuffer and js-base64), and continue to see the same error. In receiveMessage(), message is an instance of Uint8Array, though I have not shown the code to maintain clarity. Last, although it has been a while, I believe my code was working prior to getChanges() returning a bytearray. I am clearly not doing something right. Any assistance is very appreciated.

ept commented 1 year ago

Automerge.applyChanges takes an array of Uint8Arrays, not just a single Uint8Array. Try changing the last line to:

[docRef.current] = Automerge.applyChanges(docRef.current, [message]);
ept commented 1 year ago

I've made an API usability tweak in 0377389a995e49e575b72e0f6437ea5bc9603aa6: it now throws a more useful error message if you pass the wrong type of object to applyChanges().