Summary
When using a custom scheme base URL like orpc:/ in the client, RPC requests lose their path and are sent with u: "/", leading to 404 responses (“No procedure matched”). This is due to mutating url.pathname after constructing new URL(baseUrl), which is a no-op for URLs with an opaque path per the WHATWG URL spec.
This regression appears to have been introduced by a change similar to “feat(client): support search query in base url,” where safe string concatenation was replaced with url.pathname = ....
Affected packages/areas
- Client-side URL building in Standard RPC link codec (e.g., StandardRPCLinkCodec.encode)
- Custom scheme base URL (e.g., orpc:/), especially without authority (no host)
Expected behavior
Given:
- baseUrl = orpc:/
- path = ["hello"]
The encoded request should produce:
- URL href = orpc:/hello
- URL pathname = /hello
- Serialized message field u = /hello
- Server should match the procedure and not respond 404.
Actual behavior
- URL href remains orpc:/
- URL pathname stays /
- Serialized message field u = /
- Server responds with 404 “No procedure matched”
Why this happens
Per WHATWG URL Standard, pathname setter is ignored if the URL has an opaque path:
“If this’s URL has an opaque path, then return.”
Custom schemes without authority commonly produce opaque paths (e.g., orpc:/, data:, mailto:). Therefore, doing:
const url = new URL('orpc:/');
url.pathname = '/hello';
does not change the resulting href/pathname in some environments.
This explains why the RPC path vanishes when using orpc:/ as base.
Environment
- Client: @orpc/client, @orpc/client/websocket
- Transport: WebSocket / standard peer
- Standard libs: @orpc/standard-server, @orpc/standard-server-peer
- Base URL: orpc:/ (no authority)
- Path: e.g., ["hello"] → expected URL: orpc:/hello
Summary
When using a custom scheme base URL like orpc:/ in the client, RPC requests lose their path and are sent with u: "/", leading to 404 responses (“No procedure matched”). This is due to mutating url.pathname after constructing new URL(baseUrl), which is a no-op for URLs with an opaque path per the WHATWG URL spec.
This regression appears to have been introduced by a change similar to “feat(client): support search query in base url,” where safe string concatenation was replaced with url.pathname = ....
Affected packages/areas
Expected behavior
Given:
The encoded request should produce:
Actual behavior
Why this happens
Per WHATWG URL Standard, pathname setter is ignored if the URL has an opaque path:
“If this’s URL has an opaque path, then return.”
Custom schemes without authority commonly produce opaque paths (e.g., orpc:/, data:, mailto:). Therefore, doing:
does not change the resulting href/pathname in some environments.
This explains why the RPC path vanishes when using orpc:/ as base.
Environment