Skip to content
ConduitConduit

Tunnels — troubleshooting

Each section heading below is a verbatim error message (or symptom) the Tunnel produces. Search by copying a unique phrase from your logs (sudo journalctl -u conduit-tunnel). Errors are designed to name what’s wrong + WHERE to fix.

The Tunnel’s messages are in this first section. If you run the legacy v1 Docker container, its (different) error strings are in Legacy: v1 Docker container errors at the bottom.


Boot found no RELAY_URL.

Fix:

  • Confirm /etc/conduit-tunnel/env contains the RELAY_URL your operator gave you (production wss://conduit-wss.wyre.ai, staging wss://staging-wss.conduit.wyre.ai).
  • Confirm the unit references it: EnvironmentFile=/etc/conduit-tunnel/env, then sudo systemctl daemon-reload.

Your RELAY_URL isn’t wss://. Plain non-TLS ws, http://, and https:// are all rejected at boot — TLS is not optional.

Fix: correct the scheme to wss://.


FATAL: ENROLLMENT_TOKEN env var is required

Section titled “FATAL: ENROLLMENT_TOKEN env var is required”

Boot found no ENROLLMENT_TOKEN.

Fix: confirm /etc/conduit-tunnel/env contains ENROLLMENT_TOKEN=<jwt>. If your token expired, get a fresh one from your Conduit operator.


FATAL: CAPABILITIES is not a conduit-tunnel setting

Section titled “FATAL: CAPABILITIES is not a conduit-tunnel setting”

You set a CAPABILITIES env var. The Tunnel removed it on purpose: capabilities are managed in Conduit and pushed down the tunnel, not declared on the host. This guard stops a legacy v1 .env from being pasted onto a v2 host and quietly doing the wrong thing.

Fix: remove CAPABILITIES from /etc/conduit-tunnel/env. Your operator enables connectors in Conduit. (If you actually intend to run the old model, that’s the legacy container, not this Tunnel.)


relay rejected registration (reason invalid_identity / revoked_identity)

Section titled “relay rejected registration (reason invalid_identity / revoked_identity)”

The relay refused your enrollment token. Reconnecting won’t help until the token is fixed — the Tunnel stops rather than hammer the relay.

Common causes:

  • Token from the wrong environment (a staging token dialed at the prod relay, or vice versa).
  • Token expired between mint and start.
  • Token truncated on paste.

Fix: get a fresh token from your operator, minted for the same environment your RELAY_URL points at, and re-paste it cleanly into /etc/conduit-tunnel/env.


relay transient_unavailable at registration

Section titled “relay transient_unavailable at registration”

The relay hit a transient server-side problem registering your tunnel (not your fault, not your token). The Tunnel retries automatically with backoff.

Fix: none needed — it will come up on its own. If it persists for more than a few minutes, tell your Conduit operator.


Tunnel registers but /v1/mcp calls return Unknown vendor

Section titled “Tunnel registers but /v1/mcp calls return Unknown vendor”

The relay accepted your registration, but Conduit’s on-prem fork found no matching connector for the requesting user’s org.

Fix:

  • Confirm your operator has enabled and configured the connector you’re calling (you should see config applied with its slug in the Tunnel logs).
  • Confirm the requesting user’s primary org is the org your tunnel enrolled against — Conduit routes to the user’s primary (oldest) org’s tunnel.
  • If the Tunnel just restarted, wait ~60s: config re-pushes automatically, and until it lands the Tunnel is serving nothing.

Tunnel logs config applied with an error, or a connector is missing from the applied set

Section titled “Tunnel logs config applied with an error, or a connector is missing from the applied set”

Conduit pushed config, but the Tunnel couldn’t apply one of the connectors (partial apply). The applied list shows what IS serving; the error names the first failure.

Common causes:

  • A malformed connector config (e.g. an mssql block missing host or database).
  • A slug this Tunnel binary version doesn’t know.

Fix: check the Tunnel logs for the apply error, then have your operator correct the config and push again. Note: a temporarily unreachable database does NOT block apply — the mssql pool connects lazily, and the first query surfaces the connectivity error instead.


mssql: only SELECT/WITH queries are allowed

Section titled “mssql: only SELECT/WITH queries are allowed”

A query call tried a write, DDL, or multi-statement batch. The mssql connector is read-only by design — see the SQL Server guide.

Fix: working as intended. Reads (SELECT/WITH) only; writes go through the application layer.


Likely causes:

  • Egress firewall closing idle outbound connections (the WSS is long-lived).
  • DNS resolution failure for RELAY_URL.

Fix:

  • Allow outbound :443 to your WYRE relay host.
  • sudo journalctl -u conduit-tunnel -f shows reconnect attempts; the Tunnel reconnects with backoff and Conduit re-pushes config on reconnect.

Access denied: You do not have access to <connector> in this organization.

Section titled “Access denied: You do not have access to <connector> in this organization.”

The tunnel is fine — this is Conduit’s normal access-grant enforcement, and a freshly enabled connector is granted to no one. Grant the connector’s slug to the calling member/team in the org’s access editor. Its sibling, Tool "<name>" requires a higher access tier than your grants permit., means the grant exists but at too low a tier — note that unclassified tools of a proxied MCP server fail closed to the admin tier by design. See Granting access.

The save was refused because Conduit sees no live tunnel for the org. Check Connections → Tunnels — bring the tunnel online (or fix its enrollment token) and save the connection again.

Saved, but nothing answered at the server URL through the Tunnel yet

Section titled “Saved, but nothing answered at the server URL through the Tunnel yet”

Not an error — the connection is saved, but the post-save reachability probe got no answer from your server. In order of likelihood:

  1. The Tunnel hadn’t ACKed the allowlist push yet — wait a minute and check the tunnel’s page.
  2. Wrong LAN URL or port — remember it must be the address as seen from the Tunnel host.
  3. The vendor server is down, or a host firewall blocks the Tunnel host.
  4. TLS: the probe’s detail text names a certificate error → the server’s CA isn’t the PEM you pasted (or none was). Fix the Private CA certificate on the connection rather than disabling verification.

The bridge refused to reach a URL no Via-Tunnel connection covers. This is the security model working. If it’s a URL you did configure, the allowlist entry and the request URL differ in scheme/host/port — re-save the connection with the exact base URL the vendor integration calls.

lanBaseUrl must be an absolute http(s) URL

Section titled “lanBaseUrl must be an absolute http(s) URL”

The server URL must be absolute (https://cw.internal), not a bare hostname or a path.

http-bridge config: caCertPem for "…" contains no valid PEM certificate

Section titled “http-bridge config: caCertPem for "…" contains no valid PEM certificate”

(Tunnel-host log.) The pasted CA text isn’t parseable PEM — re-paste the full -----BEGIN CERTIFICATE----- block, including the header/footer lines.

Contact your Conduit operator with:

  • The verbatim error from sudo journalctl -u conduit-tunnel.
  • Your environment (production / staging).
  • Your org ID.
  • Never the ENROLLMENT_TOKEN value itself.

These are the error strings from the v1 conduit-onprem-gateway Docker container, which is still supported for already-deployed sites. New deployments use the Tunnel above. Read container logs with docker compose logs onprem-gateway.

The v1 container requires CAPABILITIES (this is the opposite of the Tunnel, which rejects it). Confirm .env contains CAPABILITIES=echo (or your granted list) — byte-for-byte, case-sensitive, matching what the token grants.

FATAL: ENROLLMENT_TOKEN structure invalid — expected 3 segments / — header or payload is not valid base64url

Section titled “FATAL: ENROLLMENT_TOKEN structure invalid — expected 3 segments / — header or payload is not valid base64url”

The v1 container’s structural-validate rejected the token shape. Cause is copy-paste truncation/corruption — re-paste the full JWT (exactly two . separators, three base64url segments).

FATAL: ENROLLMENT_TOKEN iss claim mismatch / aud claim mismatch

Section titled “FATAL: ENROLLMENT_TOKEN iss claim mismatch / aud claim mismatch”

The v1 token was minted for a different environment (or a misconfigured issuer/audience). Use a token minted for the environment your RELAY_URL points at.

Same invariants as the Tunnel — no inbound listener, wss:// only. With the stock v1 image these should not fire unless something in the environment forces a listener or a non-TLS URL.

The v1 container image is cosign-signed — see Quickstart → Verifying the legacy image. A failed verify means the image is NOT from WYRE’s published pipeline — do NOT deploy.