Skip to content

[Bug]: preview_open rejects client-local localhost URLs when using T3 Connect #8062

Description

@Lermatroid

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/web

Steps to reproduce

  1. Connect an environment to the T3 Code desktop app using Remote Link with a publicly reachable backend URL, such as a T3 Connect URL.

  2. Run a development server on the environment at port 3001.

  3. Forward that port to the machine running T3 Code so that http://localhost:3001 is reachable by the local browser.

  4. Confirm that http://localhost:3001 loads in a normal browser on the client machine.

  5. In a T3 Code thread, call:

    preview_open({ url: "http://localhost:3001" })

    Alternatively, open a blank preview and call:

    preview_navigate({ url: "http://localhost:3001" })

  6. The operation fails immediately with a generic preview automation error.

  7. Open a public page such as https://example.com, then navigate with:

    window.location.href = "http://localhost:3001"

    using preview_evaluate.

  8. The local application loads successfully, demonstrating that Chromium can reach the URL and that the failure occurs before navigation.

  9. Connect the same environment using T3 Code’s SSH connection instead of the public Remote Link.

  10. The original preview_open and preview_navigate calls now succeed.

Expected behavior

An explicit URL target such as http://localhost:3001 should be treated as a URL reachable from the client browser and passed through unchanged.

Environment-relative URL resolution should only happen when the caller uses an explicit environment-port target.

Actual behavior

T3 Code treats an explicit loopback URL as environment-relative based on the environment backend connection URL.

In apps/web/src/browser/browserTargetResolver.ts, resolveBrowserNavigationTarget reads the prepared environment connection whenever the requested URL is loopback. If the environment backend hostname is not itself loopback, it passes the URL through resolveEnvironmentPortTarget.

For a public Remote Link/T3 Connect backend hostname, resolveEnvironmentPortTarget rejects the request because the planned authenticated preview gateway does not exist:

This environment port needs the planned authenticated preview gateway; its server address is not directly private-network reachable.

As a result, T3 Code rejects a URL that is already reachable from the client browser. The failure occurs before Chromium navigation.

The agent only receives a generic message such as:

Preview automation open failed on client <client-id>.

The original resolver error is also hidden by the preview automation error serialization.

Possible fix

Preserve explicit url targets unchanged, including loopback URLs.

Only rewrite URLs to the environment hostname when the caller explicitly supplies an environment-port target. This preserves the semantic distinction already present in BrowserNavigationTarget:

  • url: directly reachable from the browser
  • environment-port: relative to the connected environment

If automatic rewriting of explicit localhost URLs must remain, there should be a way to distinguish client-local forwarded ports from environment-relative ports.

Impact

Major degradation or frequent failure

Version or commit

0.0.34-nightly.20260824.1172 / b4be33f

Environment

macOS, T3 Code desktop nightly, Codex provider, environment connected using Remote Link through T3 Connect, client-side SSH port forwarding for localhost:3001

Logs or stack traces

Preview automation open failed on client <client-id>.
Preview automation navigate failed on client <client-id>.

The server trace identifies PreviewAutomationExecutionError, but the underlying resolver cause is not included in the serialized error.

Screenshots, recordings, or supporting files

No response

Workaround

Connecting the environment through T3 Code’s built-in SSH support makes the prepared backend URL loopback-local, so explicit localhost URLs are left unchanged.

Another workaround is assigning window.location.href through preview_evaluate, which bypasses resolveBrowserNavigationTarget, although this is unsuitable for normal agent browser use.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething is broken or behaving incorrectly.needs-triageIssue needs maintainer review and initial categorization.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions