denoland/deno · error · TypeError
A writable stream is not associated with the writer
Error message
A writable stream is not associated with the writer
What it means
TypeError thrown by the WritableStreamDefaultWriter.desiredSize getter when this[_stream] is undefined (ext/web/06_streams.js). A writer only references its stream while it holds the lock; after releaseLock() (or after the stream errors/finalizes and the association is dropped), desiredSize can no longer be computed and the getter throws.
Source
Thrown at ext/web/06_streams.js:7529
this[_brand] = _brand;
setUpWritableStreamDefaultWriter(this, stream);
}
/** @returns {Promise<void>} */
get closed() {
try {
webidl.assertBranded(this, WritableStreamDefaultWriterPrototype);
} catch (err) {
return PromiseReject(err);
}
return this[_closedPromise].promise;
}
/** @returns {number} */
get desiredSize() {
webidl.assertBranded(this, WritableStreamDefaultWriterPrototype);
if (this[_stream] === undefined) {
throw new TypeError(
"A writable stream is not associated with the writer",
);
}
return writableStreamDefaultWriterGetDesiredSize(this);
}
/** @returns {Promise<void>} */
get ready() {
try {
webidl.assertBranded(this, WritableStreamDefaultWriterPrototype);
} catch (err) {
return PromiseReject(err);
}
return this[_readyPromise].promise;
}
/**
* @param {any} reasonView on GitHub (pinned to 9ad36f7a2c)
Solutions
- Read desiredSize before calling releaseLock(), while the writer still holds the lock.
- After releasing, call stream.getWriter() again to get a valid writer before querying desiredSize.
- Track the released state in your own variable and skip desiredSize queries once released.
- Wrap the access in try/catch TypeError when the lock state cannot be proven.
Example fix
// before const writer = ws.getWriter(); writer.releaseLock(); console.log(writer.desiredSize); // TypeError: no stream associated // after const writer = ws.getWriter(); const size = writer.desiredSize; // read while locked writer.releaseLock();
Defensive patterns
Strategy: try-catch
Validate before calling
// Track the lock yourself: after releaseLock() the writer is inert.
let released = false;
function desiredSizeOrZero(writer) {
if (released) return 0; // or null per your backpressure convention
return writer.desiredSize;
}
// ... on cleanup: released = true; writer.releaseLock(); Try / catch
let size;
try {
size = writer.desiredSize;
} catch (err) {
if (err instanceof TypeError && /not associated with the writer/.test(err.message)) size = null;
else throw err;
} Prevention
- Read desiredSize before releaseLock(), in the same critical section.
- Never reuse a writer object after releasing; call getWriter() fresh.
- Keep a `released` flag alongside the writer in wrapper classes.
When it happens
Trigger: writer.releaseLock() followed by reading writer.desiredSize; inspecting desiredSize after the stream was aborted/errored far enough to detach the writer; storing a writer past its lock lifetime and polling its desiredSize.
Common situations: Backpressure checks in cleanup/monitoring code that run after releaseLock; loops that release the lock on error and then log desiredSize for diagnostics; using one writer object after re-acquiring with getWriter() on the same stream.
Related errors
- The stream is already locked
- ${prefix}: WritableStream does not support 'type' in the und
- Response body is already used
- ERR_HTTP2_NO_SOCKET_MANIPULATION
- ERR_INVALID_ARG_TYPE
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/8a426a7b594efaba.
Report an issue: GitHub.