Skip to content

Surface hosted tunnel conflict messages#19

Closed
mmkal wants to merge 3 commits into
mmkal/26/05/24/hosted-ownership-tokensfrom
mmkal/26/05/24/hosted-connect-conflict-message
Closed

Surface hosted tunnel conflict messages#19
mmkal wants to merge 3 commits into
mmkal/26/05/24/hosted-ownership-tokensfrom
mmkal/26/05/24/hosted-connect-conflict-message

Conversation

@mmkal
Copy link
Copy Markdown
Contributor

@mmkal mmkal commented May 23, 2026

Summary

Rejected hosted tunnel connects now carry the Worker rejection reason through to library and CLI users. When an anonymous hosted tunnel name is already active under a different owner token, createCaptunTunnel can report the 409 Conflict body (Tunnel name is already connected) instead of only WebSocket connection failed, and the CLI treats that known Captun response as a name-in-use conflict rather than a DNS/certificate setup problem.

Behavior

await createCaptunTunnel({
  url: \"https://demo.captun.sh/__captun-connect\",
  fetch: () => new Response(\"ok\"),
});
// If the Worker rejects with the Captun ownership conflict:
// CaptunTunnelConnectError: WebSocket connection failed: 409 Conflict: Tunnel name is already connected

The CLI now follows that known conflict with guidance to pick a different --name or stop the existing anonymous client. Unrelated 409 responses keep the existing DNS/custom-domain troubleshooting path.

Implementation Notes

Node’s WebSocket ErrorEvent does not expose the rejected upgrade response status/body directly. To make this deterministic for the hosted Worker conflict, the library performs a follow-up fetch to the same connect URL after a pre-open WebSocket failure and uses any non-2xx response body as rejection detail. That diagnostic probe has a short abort timeout and falls back to the generic WebSocket failure if the HTTP request does not answer.

This works for the current Worker conflict path because the Worker returns 409 before it attempts to create the WebSocket upgrade response. If another runtime/server fails the upgrade without returning an equivalent plain HTTP response to that follow-up request, the error remains the generic WebSocket failure.

Verification

  • pnpm exec vitest run test/worker.test.ts test/cli.test.ts (first run hit a one-off Miniflare body-read flake, narrowed rerun and full rerun passed)
  • pnpm run check
  • pnpm test
  • pnpm run build

Note

Medium Risk
Changes tunnel connection error handling by probing failed WebSocket upgrades via HTTP and altering CLI messaging based on parsed rejection content; mistakes could misclassify failures or add minor latency on connect errors.

Overview
Improves tunnel connect failure reporting by adding CaptunTunnelConnectError and, on pre-open WebSocket errors, doing a short-timeout HTTP probe of the connect URL to capture the server’s rejection status/body (e.g. 409 Conflict: Tunnel name is already connected).

Updates the CLI to detect this specific active-tunnel/name-in-use conflict and show actionable --name guidance instead of generic DNS/cert troubleshooting, while keeping the existing troubleshooting path for other failures.

Adds Vitest coverage for the new rejection-surfacing behavior (including probe timeout fallback) and for the CLI’s conflict vs non-conflict messaging behavior.

Reviewed by Cursor Bugbot for commit 04328e3. Bugbot is set up for automated code reviews on this repo. Configure here.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 23, 2026

Open in StackBlitz

npm i https://pkg.pr.new/captun@19

commit: 04328e3

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit e0475ba. Configure here.

Comment thread src/index.ts
@mmkal
Copy link
Copy Markdown
Contributor Author

mmkal commented May 24, 2026

Superseded by #20, which is now the combined hosted safety PR with this conflict-message work included.

@mmkal mmkal closed this May 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant