Problem
random.uuidv4() (and random.uint32()) can throw an unhandled OperationError (DOMException, code 0) when crypto.getRandomValues() fails transiently in Firefox.
We observed this in production on Firefox 148.0 / Ubuntu during Yjs Doc construction, which calls uuidv4() to generate the document GUID. The error is unrecoverable and crashes the application.
Stack trace (minified, from Yjs bundle)
OperationError: The operation failed for an operation-specific reason
Df → crypto.getRandomValues.bind(crypto) // lib0/webcrypto.js
Kb → uuidv4() // lib0/random.js
t → new Doc({ guid: uuidv4() }) // yjs
Reproduction
This is a transient failure — Firefox's Web Crypto implementation can occasionally throw OperationError from getRandomValues() due to process isolation or entropy pool issues. It's rare but not recoverable without a try/catch.
Suggested fix
Two complementary improvements:
1. Prefer crypto.randomUUID() for uuidv4()
All modern browsers (Firefox 95+, Chrome 92+, Safari 15.4+) support crypto.randomUUID(), which returns a UUID v4 string directly without going through getRandomValues. This avoids the failure entirely for the most common use case.
const uuidv4 = typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function'
? () => crypto.randomUUID()
: () => uuidv4Template.replace(/[018]/g, c => (c ^ uint32() & 15 >> c / 4).toString(16))
2. Add a try/catch fallback in uint32()
The module comment already says "falls back to Math.random if the browser does not support crypto", but this fallback isn't actually implemented for uint32(). A defensive fallback would protect all callers:
const uint32 = () => {
try {
return webcrypto.getRandomValues(new Uint32Array(1))[0]
} catch {
return (Math.random() * 2 ** 32) >>> 0
}
}
Workaround
We're currently wrapping new Doc() in a retry loop on our side, which works since the failure is transient. But the fix belongs in lib0 since every Yjs consumer is affected.
Environment
- lib0: 0.2.117
- yjs: 13.6.14
- Browser: Firefox 148.0 on Ubuntu
- Error:
OperationError (DOMException, code 0) from crypto.getRandomValues
Problem
random.uuidv4()(andrandom.uint32()) can throw an unhandledOperationError(DOMException, code 0) whencrypto.getRandomValues()fails transiently in Firefox.We observed this in production on Firefox 148.0 / Ubuntu during Yjs
Docconstruction, which callsuuidv4()to generate the document GUID. The error is unrecoverable and crashes the application.Stack trace (minified, from Yjs bundle)
Reproduction
This is a transient failure — Firefox's Web Crypto implementation can occasionally throw
OperationErrorfromgetRandomValues()due to process isolation or entropy pool issues. It's rare but not recoverable without a try/catch.Suggested fix
Two complementary improvements:
1. Prefer
crypto.randomUUID()foruuidv4()All modern browsers (Firefox 95+, Chrome 92+, Safari 15.4+) support
crypto.randomUUID(), which returns a UUID v4 string directly without going throughgetRandomValues. This avoids the failure entirely for the most common use case.2. Add a try/catch fallback in
uint32()The module comment already says "falls back to Math.random if the browser does not support crypto", but this fallback isn't actually implemented for
uint32(). A defensive fallback would protect all callers:Workaround
We're currently wrapping
new Doc()in a retry loop on our side, which works since the failure is transient. But the fix belongs in lib0 since every Yjs consumer is affected.Environment
OperationError(DOMException, code 0) fromcrypto.getRandomValues