Skip to content

URL pathname assignment fails for custom scheme (opaque path), causing RPC path to be lost #1043

@dmitriyzhirma

Description

@dmitriyzhirma

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

  1. Client-side URL building in Standard RPC link codec (e.g., StandardRPCLinkCodec.encode)

  2. 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

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions