ReadableStream cannot be returned through a forwarded stub
Maintainers usually reply within 2 days
Nobody has claimed this yet.
Assessment
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Newbie friendliness
- 68/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Quiet
- Tech stack
- javascript, typescript
Research direction
Start with RpcPayload.ensureDeepCopied() and getHookForReadableStream, then reproduce the two-session broker example from the issue. Verify that a ReadableStream returned through childStub.dup() reaches the caller without the owned-payload error, while direct-session behavior remains unchanged.
Written by the indexing model from the issue text.
Description
A ReadableStream returned by an RPC method works when the caller holds a direct session to the target. It throws when the call is forwarded through an intermediate session, such as when a broker returns a dup of a stub it holds to a third party.
- Create a session between a broker and a child. The child has a method that returns a ReadableStream.
- Create a second session between a caller and the broker. The broker exposes a method that returns
childStub.dup(). - From the caller, resolve that stub and call the stream-returning method on it.
Expected: the caller receives a ReadableStream, the same as it would on a direct session.
Actual: Error: owned payload shouldn't contain raw ReadableStreams.
Cause: RpcPayload.ensureDeepCopied() sets source to "owned" after the first hop. getHookForReadableStream handles "params" and "return" and throws on anything else. Regular stubs forward across the same two sessions without error, so only streams hit this.
import { newMessagePortRpcSession, RpcTarget } from "capnweb";
class Child extends RpcTarget {
async ping() { return "pong"; }
async tail() {
let i = 0;
return new ReadableStream({
pull(c) { if (i >= 3) return c.close(); c.enqueue(new Uint8Array([i++])); }
});
}
}
class Broker extends RpcTarget {
constructor(child) { super(); this.child = child; }
async resolveChild() { return this.child.dup(); }
}
const childChan = new MessageChannel();
newMessagePortRpcSession(childChan.port2, new Child());
const childFromBroker = newMessagePortRpcSession(childChan.port1);
const brokerChan = new MessageChannel();
newMessagePortRpcSession(brokerChan.port2, new Broker(childFromBroker));
const broker = newMessagePortRpcSession(brokerChan.port1);
const child = await broker.resolveChild();
console.log(await child.ping()); // "pong"
await child.tail(); // throws
Tested on capnweb 0.10.0. The same error string is present in 0.8.0.
Workaround: return an RpcTarget with a next() method instead of the stream, and rebuild the stream on the caller side.
- Dominant language
- TypeScript
- Stars
- 4k
- Forks
- 151
- Avg merge
- 16h 46m
- Merged PRs (30d)
- 2
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from cloudflare/capnweb
-
Difficulty 2/5 1-3 hours Newbie friendliness 81/100
cloudflare/capnweb#293 ·
Maintainers usually reply within 2 days
-
enhancement
Difficulty 5/5 Over a week Newbie friendliness 35/100
cloudflare/capnweb#269 · 2 comments ·
Maintainers usually reply within 2 days
-
Difficulty 3/5 1-2 days Newbie friendliness 48/100
cloudflare/capnweb#260 ·
Maintainers usually reply within 2 days
-
onRpcBroken should return a Disposable so registrations can be undoneMay be free again A pull request for this issue was closed without being merged. Openenhancement
Difficulty 4/5 3-5 days Newbie friendliness 35/100
cloudflare/capnweb#234 · 1 comment ·
Maintainers usually reply within 2 days
-
support `Map` serialization typePossibly taken @srikrsna claimed this 95 days ago. Open
Difficulty 3/5 1-2 days Newbie friendliness 55/100
cloudflare/capnweb#230 ·
Maintainers usually reply within 2 days
All issues in cloudflare/capnweb
Similar issues
-
bug chore
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
Maintainers usually reply within 1 day
-
🧩 Docs job fails type-checking `generate-plugin-docs.ts`Possibly taken @X-Guardian claimed this today. Opendiscussion
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
Maintainers usually reply within 1 day
-
envision-erpnext
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
Maintainers usually reply within 1 day
-
bug sharing & sync
Difficulty 1/5 Under an hour Newbie friendliness 92/100
Maintainers usually reply within 1 day