A throwing event handler permanently breaks future document events and observers
Author: ben-ashton-safetyvantageCreated Aug 21, 2026Updated Aug 21, 2026
Labelsbug
Please save me some time and use the following template. In 90% of all issues I can't reproduce the problem because I don't know what exactly you are doing, in which environment, or which y-* version is responsible. Just use the following template even if you think the problem is obvious.
Checklist
- Are you reporting a bug? Use github issues for bug reports and feature requests. For general questions, please use https://discuss.yjs.dev/
- Try to report your issue in the correct repository. Yjs consists of many modules. When in doubt, report it to https://github.com/yjs/yjs/issues/
Describe the bug
If a listener for any of the following events throws, listeners and observers stop working for the remaining lifetime of the document: beforeAllTransactions, beforeTransaction, afterTransactionCleanup, update, updateV2, subdocs
To Reproduce Steps to reproduce the behavior:
import * as Y from '@y/y';
const doc = new Y.Doc();
const type = doc.get('a');
let pushCount = 0;
function push() {
pushCount++;
console.log(`Pushing ${pushCount}`);
type.push([pushCount]);
}
let firstObserveCount = 0;
type.observe(() => {
firstObserveCount++;
});
// Attach an update listener that throws
const listener = () => {
console.log('Throwing from update listener');
throw new Error('provider error');
};
doc.on('update', listener);
// Write to the document and trigger the throwing listener
try {
push();
} catch (error) {
console.log('write threw:', error.message);
}
// Detach the throwing listener, document is permanently broken either way
doc.off('update', listener);
let secondObserveCount = 0;
type.observe(() => {
secondObserveCount++;
});
let secondUpdateCount = 0;
doc.on('update', () => {
secondUpdateCount++;
});
push();
push();
push();
console.log();
console.log(`Expected first observer to be called ${pushCount} times, got: ${firstObserveCount}`);
console.log(`Expected second observer to be called ${pushCount - 1} times, got: ${secondObserveCount}`);
console.log(`Expected second update listener to be called ${pushCount - 1} times, got: ${secondUpdateCount}`);
console.log('Array content:', type.toArray());
Expected behavior See output of minimal reproduction
Screenshots N/A
Environment Information
- Only tested with node, but likely applicable everywhere else
- Yjs version and the versions of the y-* modules you are using: @y/[email protected], also present in YJS v13 stable release
Additional context N/A
- I'm a sponsor
- This issue is a blocker for my project.
Source: yjs/yjs