Skip to content

cli: add a way to reset/discard a stuck pending OpenTunnel tunnel (pair --remote) #54624

Open

Description

@IgTriguero

Summary

opencode pair --remote has no built-in way to discard a pending OpenTunnel tunnel. If a tunnel gets stuck while pending (e.g. it was created during a service-side outage), every subsequent pair --remote resumes that same broken tunnel instead of creating a fresh one, and the user cannot recover without manually deleting files from their data directory.

Context

Came out of #54596. During the opentunnel.xyz outage (525s from European Cloudflare colos), a pending tunnel was created and certificate issuance kept failing. After the service recovered:

  • pair --remote kept resuming the stale pending tunnel (progress label resuming-certificate), still failing with 525s on GET /api/tunnel/<id>/certificate.
  • The background service also kept retrying that same tunnel every ~30s, so the failure persisted locally long after the outage cleared.
  • There was no CLI flag/command to discard it. The only recovery was manually removing pending.json, token, and private-key.pem from ~/.local/share/opentunnel/<profile>/ — after that, a fresh tunnel was created and issued a certificate immediately.

So a transient service outage turned into a persistent local failure with no supported recovery path.

Proposal

Expose a way to reset/discard the pending OpenTunnel state, for example:

  • opencode pair --reset (or --fresh), or
  • opencode service remote reset, or
  • both: a reset action plus a small status view (show whether a pending or completed tunnel exists for the profile).

Optional: when the tunnel keeps failing across retries, mention the reset option in the error/retry message.

Implementation notes

The internal pieces already exist (OpenTunnelClient.tunnel.pending, .resume, .remove — the last one clears both the profile and the pending state). The CLI surface just doesn't expose them; a minimal version could be a pair --reset flag calling the existing pending-discard path.

Environment

  • opencode 2.0.26, Windows 11 (win32 x64)

Activity

  1. opencode-agent commented on Oct 11, 2026

    @opencode-agent
    Contributor

    Thanks for the detailed write-up and for following up on #54596!

    To restate the request: opencode pair --remote and the background service always pick up an existing pending OpenTunnel tunnel again. If that tunnel got stuck, for example during the opentunnel.xyz outage, the only way to start fresh is to delete pending.json, token and private-key.pem from the OpenTunnel data folder by hand. You're asking for a supported way to discard it, such as opencode pair --reset/--fresh or opencode service remote reset. A status view and a hint in the retry error message would be nice extras.

    I checked the current code, and nothing in the CLI exposes this today. Interrupted certificate issuance is designed to resume on the next run. Maintainers will consider the request.

    Related:

    Until something like this exists, the manual workaround you described (removing those three files from ~/.local/share/opentunnel/<profile>/) is the way to recover.

  2. IgTriguero commented on Oct 11, 2026

    @IgTriguero
    Author

    Happy to take this one if it's not already being worked on.

    The SDK already exposes tunnel.remove() publicly, so this can be CLI-only in packages/cli: add a --reset flag to opencode pair (or a service remote reset command) that discards the stored pending/profile state via tunnel.remove() and then runs the normal ensure flow, so a wedged pending tunnel can be replaced without manually deleting files under ~/.local/share/opentunnel/<profile>/.

    Optionally, once the background service has been retrying for a while, the "remote access tunnel unavailable; retrying" warning could point at the reset option.

    Let me know if that direction works and I'll open a PR.

  3. IgTriguero commented on Oct 14, 2026

    @IgTriguero
    Author

    Opened #55502 — a small CLI-only implementation of the --reset idea: it discards the stored OpenTunnel state (tunnel.remove() for a completed tunnel, plus the profile directory which is what clears a stuck pending issuance) and then runs the normal pairing flow. The PR includes tests for the wedged-pending case and a reviewer script for reproducing it without an outage.

    I know CONTRIBUTING asks for design approval before feature PRs. Happy to close or rework it if you would rather this waited, or if you prefer a different shape (for example a service remote reset command).

  4. thdxr commented on Oct 15, 2026

    @thdxr
    Member

    Context from the OpenTunnel side, in case it helps decide on this and #55502. The server-side causes of tunnels getting stuck pending are fixed:

    • Oct 12 (anomalyco/opentunnel@910f46e): certificate issuance no longer fails permanently on transient ZeroSSL or Cloudflare errors (525, missing nonce, 502). It retries with backoff for up to 24 hours, and tunnels stuck by the earlier behaviour were re-queued automatically.
    • Oct 14 (anomalyco/opentunnel@a735dea): issuance stuck on "authorization ended in pending" now recovers, and those tunnels were re-queued too.
    • Clients 0.5.1 keep using a saved, unexpired certificate when the API is briefly unavailable, and retry transient 5xx responses.

    So a tunnel created during an outage should now finish issuing on its own once the service recovers, without a local reset. A reset command may still be worth having as an escape hatch, but that's the opencode maintainers' call, so I'm leaving this open.

    — from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊

  5. ahxxm commented on Oct 15, 2026

    @ahxxm

    I can confirm that a stuck tunnel recovers, although mine isn't a pending one, it stopped working somewhere around 12 hours ago, restarting opencode didn't help before above comment, after that I

    • re-issued a working tunnel by: stop remote -> move tunnel profile dir -> reissue -> wait
    • saw the comment, I followed similar step to recover the stuck tunnel: stop remote -> move back tunnel file dir containing id and credentials -> start remote -> reconfigure custom route
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions