chenhg5/cc-connect · error
connect permission bridge: %w
Error message
connect permission bridge: %w
What it means
Relay wraps net.DialTimeout failures as 'connect permission bridge: %w'. The hook dials the cc-connect session's TCP listener (5s timeout) to ask the human for a permission decision; if the connection cannot be established the hook fails closed (deny). Per the code comment, dial failures are intentionally fast because the listener is expected to already be up.
Source
Thrown at agent/antigravityhook/protocol.go:50
func Relay(in io.Reader, out io.Writer, address, token string) error {
if strings.TrimSpace(address) == "" || strings.TrimSpace(token) == "" {
return fmt.Errorf("permission bridge environment is missing")
}
input, err := io.ReadAll(io.LimitReader(in, maxHookInput+1))
if err != nil {
return fmt.Errorf("read hook input: %w", err)
}
if len(input) > maxHookInput {
return fmt.Errorf("hook input exceeds %d bytes", maxHookInput)
}
if !json.Valid(input) {
return fmt.Errorf("hook input is not valid JSON")
}
conn, err := net.DialTimeout("tcp", address, bridgeDialTimeout)
if err != nil {
return fmt.Errorf("connect permission bridge: %w", err)
}
defer func() { _ = conn.Close() }()
// The listener is started before agy runs this hook, so dial failures should
// fail closed quickly. After connect, wait much longer for a human response.
_ = conn.SetDeadline(time.Now().Add(bridgeResponseTimeout))
if err := json.NewEncoder(conn).Encode(BridgeRequest{Token: token, HookInput: input}); err != nil {
return fmt.Errorf("send permission request: %w", err)
}
var response BridgeResponse
if err := json.NewDecoder(io.LimitReader(conn, 64<<10)).Decode(&response); err != nil {
return fmt.Errorf("read permission response: %w", err)
}
switch response.Decision {
case "allow", "deny":
default:
return fmt.Errorf("invalid permission decision %q", response.Decision)View on GitHub (pinned to 4000b2338a)
Solutions
- Confirm cc-connect (and the antigravity session) is still running while agy executes
- Verify CC_CONNECT_AGY_PERMISSION_ADDR matches the listener the session actually bound
- Test connectivity: `nc -vz <host> <port>` from the same environment the hook runs in
- Check firewall/container networking allows the hook to reach the bridge address
- If it races session shutdown, this fail-closed behavior is expected — treat it as a deny
Example fix
// before $ CC_CONNECT_AGY_PERMISSION_ADDR=127.0.0.1:0 agy ... // after $ CC_CONNECT_AGY_PERMISSION_ADDR=127.0.0.1:47391 agy ... # port from the live listener
Defensive patterns
Strategy: retry
Validate before calling
conn, err := net.DialTimeout("tcp", addr, 2*time.Second)
if err != nil { log.Fatalf("bridge %s unreachable before launching agy: %v", addr, err) }
conn.Close() Try / catch
if err := Relay(...); err != nil {
var ne net.Error
if errors.As(err, &ne) || strings.HasPrefix(err.Error(), "connect permission bridge:") {
// treat as deny; optionally retry with backoff while session is alive
}
} Prevention
- Verify the bridge address env matches the live listener port
- Ensure the session outlives the agy hook (no concurrent Stop)
- Check firewall/container networking for the bridge port
- `nc -vz host port` from the hook environment as a preflight
When it happens
Trigger: DialTimeout to CC_CONNECT_AGY_PERMISSION_ADDR fails: cc-connect listener not running, session already exited, wrong address/port in env, firewall blocking loopback/tcp, or listener bound after the hook ran.
Common situations: Stale env vars pointing at a dead session's port; agy hook racing session shutdown; cc-connect crashed while agy kept running; Docker/container networking isolating the hook from the host port.
Understand the failure class
Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.
Related errors
- send permission request: %w
- reasonix: POST %s: %w
- %s: image download: %w
- qq: ws connect failed (%s): %w
- telegram: connect failed: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/7faa71a5b43827b1.
Report an issue: GitHub.