rivet-dev / rivet-dev/actors

Serverless listener forwards /start to the application when basePath is "/"

Open Beginner friendly
#5,755 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
6.1k
Forks
250
Avg merge
2d 8h
Merged PRs (30d)
96

Description

What happens

With serverless.basePath: "/" and an application passed to registry.listen(), the Rust listener forwards the engine's POST /start to the application instead of handling it. Same for /health, /metadata and /metrics. Actors on that pool never start. The same config works through registry.handler().

Where

handles_listener_request in rivetkit-rust/packages/rivetkit-core/src/serverless.rs:

let request_path = parsed.path();
if request_path != base_path && !request_path.starts_with(&format!("{base_path}/")) {
	return false;
}

Why it happens

normalize_base_path(Some("/")) returns "/", so the prefix check looks for "//". No request path starts with //, so everything except / itself returns false. serverless_http.rs only hands a request to the runtime when this returns true or when there's no application, so /start ends up in the user's handler.

route_path already handles a root base path correctly. It's only this check. The TypeScript side special-cases it in isServerlessStartRequest (basePath === "/" ? "" : ...), which is why registry.handler() works.

Reproduction

Add to rivetkit-rust/packages/rivetkit-core/tests/serverless.rs:

#[test]
fn listener_reserves_framework_routes_for_root_base_path() {
	let base_path = normalize_base_path(Some("/"));
	for path in ["/", "/start", "/health", "/metadata", "/metrics"] {
		assert!(
			handles_listener_request(&base_path, &format!("http://internal{path}")),
			"root base path should reserve {path}"
		);
	}
	assert!(!handles_listener_request(&base_path, "http://internal/application"));
}

cargo test -p rivetkit-core --lib listener_reserves_framework_routes_for_root_base_path fails with root base path should reserve /start.

Expected behaviour

With a root base path the listener handles /, /start, /health, /metadata and /metrics itself and forwards everything else to the application.

Suggested fix

Treat base_path == "/" as matching every request path before the prefix check. route_path already returns the right route in that case. Happy to open a PR.

Environment

  • upstream/main at 78336a1a0
  • Linux 7.2.5-3-omarchy
  • rustc 1.98.1 (48a229cea 2026-09-01), cargo 1.98.1 (797e8a9bc 2026-08-05)

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in rivetkit-rust/packages/rivetkit-core/src/serverless.rs at handles_listener_request, then review route_path and the related serverless tests. Run the named cargo test with the root base-path reproduction; done means /, /start, /health, /metadata, and /metrics are reserved while /application is forwarded to the application.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
backend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
90/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.