# What changed in loro-crdt

> 48 changes in loro-crdt 1 from its official release notes, upgrade guides and advisories: 11 breaking, 1 security, 6 new APIs and options. Each one cited. Sources checked 2026-10-30. HTML: https://unstale.sh/npm/loro-crdt/

To see which of these apply to a repository, run `npx @unstale/cli init` in it.

## loro-crdt 1

### Breaking changes

- The error gains HistoryUnreadable(LoroError) and is non-exhaustive, so downstream exhaustive matches must add a wildcard arm. (1.17.0) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.17.0)
- This changes from a unit struct to a struct with a private field plus a same-named constant; downstream callers must use Err(_) rather than an exhaustive Err(FrontiersNotIncluded) match. (1.17.0) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.17.0)
- Fallible history operations return decode errors for unreadable change blocks instead of panicking or wrapping the failure as Unknown; affected Rust methods now return LoroResult. (1.17.0) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.17.0)
- Other serde deserialization of LoroValue now rejects nesting beyond 128 levels with an error. (1.17.0) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.17.0)
- Undo and redo return application errors after rolling back failed inverse operations, preserving document state and history for retry; failed operations emit no events. (1.17.0) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.17.0)
- Failed calls leave the document, history, and subscribers unchanged, while preserving prior uncommitted edits. Applying a diff with a missing tree parent now throws. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)
- Malformed movable-list operations and out-of-bounds Text operations return errors without applying the import or leaving the document unusable. Invalid sequence positions at or above 1,073,741,822 are rejected during decoding. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)
- Imports that reuse existing operation IDs for different content, skip peer counters, or contain invalid operations fail without changing the document; rejected imports leave it usable. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)
- Malformed movable-list operations return errors without applying the import, including when an operation depends on another change in the same import. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)
- Malformed movable-list operations and out-of-bounds Text operations return errors without applying the import or leaving the document unusable. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)
- Shallow and state-only snapshots no longer retain map/list child containers deleted before the shallow root; tree-node metadata remains available for revival. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)

### Security

- Encoded cursors with negative position counters and directly constructed invalid cursors are rejected with readable decode errors before document history is accessed. (1.17.0) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.17.0)

### New APIs and options

- The error is now non-exhaustive and gains a HistoryUnreadable variant for unreadable history. (1.17.0) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.17.0)
- Exports remote updates waiting for missing causal dependencies in the existing updates format, so they can be persisted and later imported after a separately saved snapshot. (1.17.0) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.17.0)
- Applications can set a finite decoded container value cache limit; zero disables the cache, lowering the limit safely evicts cached values, and forks inherit an independent local setting. (1.17.0) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.17.0)
- Reads visible container trees as one JSON string built in Rust, avoiding per-value WASM-to-JS calls while preserving node shapes, IDs, formatting, and root filtering. (1.17.0) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.17.0)
- The error gains a DecodeError variant. (1.17.0) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.17.0)
- Pass `{ fullState: true }` to `applyDiff` when restoring a mergeable child that may still exist as hidden state, aligning its full content instead of appending to it. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)

### Performance

- When a multi-blob batch starts with a full snapshot in an empty, attached document, it uses lazy fast-snapshot import and applies remaining updates in one checkout while preserving rollback. (1.17.0) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.17.0)
- Imports of List and Tree operations no longer copy the peer's last change block on every import to keep a rollback copy; many small imports are about 30% faster. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)
- The first import concurrent with a local edit to a map on a shallow document adds each shallow-root map's entries only when a diff needs that map, avoiding eager decoding of every map. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)

### Fixes and other changes

- Restores the Rust method’s return type to VersionVector for source compatibility with versions before 1.17.0; it panics on resolution failure after releasing document locks. (1.17.1) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.17.1)
- The TypeScript declaration return type is corrected to match runtime behavior. (1.17.0) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.17.0)
- fork() and forkAt() preserve the full text style configuration, including defaults for previously unused style keys. (1.17.0) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.17.0)
- The TypeScript declaration callback parameter is corrected to match runtime behavior. (1.17.0) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.17.0)
- Undo and redo use element identities for native moves, sets, and inverse insertion deletes, fixing duplicate scalar elements and lost gaps after concurrent moves. (1.17.0) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.17.0)
- Pending changes are retained when importing a snapshot into a document that holds only pending changes. (1.17.0) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.17.0)
- The TypeScript declaration key type is corrected to match runtime behavior. (1.17.0) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.17.0)
- Each undo or redo call consumes at most one recorded item; a consumed no-op returns false and creates no opposite-stack item, leaving other history available. (1.17.0) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.17.0)
- Tree checkouts between concurrent versions no longer retain nodes absent from the target or panic when a node's child is created without the node. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)
- The `updates-in-range` export mode no longer panics when spans contain several non-contiguous or overlapping ranges from one peer; all ranges are exported. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)
- Documents forked or snapshotted at a version with an unclosed style mark can be read without trapping; the start anchor styles nothing until its end arrives. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)
- Returns the correct change for lamports loaded from snapshots, including peers with many stored blocks. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)
- Returns `undefined` for cursors on Map, Tree, Counter, or unknown containers instead of trapping. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)
- Checkout updates the last editor for map entries and movable-list items whose values are unchanged between versions, so the reported writer is correct. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)
- A root container touched by document history is retained after importing that history even if its operations produce an empty value. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)
- Tree-node metadata under a deleted ancestor and movable-list children no longer remain incorrectly deleted after the subtree or child is revived. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)
- `applyDiff` now keeps every child container moved by a diff and preserves their order; undo and redo use the same corrected behavior. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)
- A map event containing an unknown container value is delivered with its known keys; only the unknown child's entry is omitted. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)
- Throws a readable error when a container's parent has an unknown type, rather than trapping. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)
- Failed calls leave the document, history, and subscribers unchanged, while preserving prior uncommitted edits. Reverting a mergeable child no longer duplicates its content. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)
- Text insertion beside style anchors now respects the mark boundary, and WASM deletes spanning separate inserts record the correct character IDs when astral characters are involved. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)
- Snapshots and forked documents can resolve tree-node metadata parents created under deleted parents; corrupted change blocks no longer make queries trap, and later history operations report a parse error. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)
- Callbacks retain representable events in a batch that touches an unknown container instead of losing the whole batch. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)
- Committing a transaction that merges backspaces over astral characters no longer panics in WASM when the document has a subscriber or an UndoManager. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)
- Importing moves out of deleted subtrees now emits events for restored descendant nodes, and moves under deleted nodes emit the applicable delete event. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)
- Undo and redo no longer duplicate mergeable-child content, and a peer's own edit remains undoable after a remote undo restores the child it edited. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)
- Undoing a step that would recreate an unknown container throws without changing the document; the step is dropped and its edits remain for subsequent rebased undo operations. (1.16.4) — [release notes](https://github.com/loro-dev/loro/releases/tag/loro-crdt%401.16.4)
