chenhg5/cc-connect · error
read permission response: %w
Error message
read permission response: %w
What it means
Relay in agent/antigravityhook/protocol.go sends a permission-hook request to the cc-connect bridge over a TCP connection and decodes the JSON BridgeResponse. This error wraps any failure while reading/decoding the response from the bridge socket — the connection closed early, the peer sent non-JSON bytes, the payload exceeded the 64 KiB cap, or a network I/O error occurred. It exists so the hook fails closed with context instead of silently treating a broken bridge as an allow.
Source
Thrown at agent/antigravityhook/protocol.go:63
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)
}
if err := json.NewEncoder(out).Encode(response); err != nil {
return fmt.Errorf("write hook response: %w", err)
}
return nil
}
View on GitHub (pinned to 4000b2338a)
Solutions
- Restart the cc-connect session that owns the permission bridge, then re-run the agent operation that triggered the hook
- Verify CC_CONNECT_AGY_PERMISSION_ADDR points to the live bridge socket and that no other process has claimed that port
- Check cc-connect logs for a bridge listener crash (e.g. panics in the permission handler) and fix the underlying crash
- Re-run the hook manually to see if the failure is transient (bridge was momentarily unavailable)
Defensive patterns
Strategy: try-catch
Validate before calling
if addr := os.Getenv("CC_CONNECT_AGY_PERMISSION_ADDR"); addr == "" { t.Fatal("bridge address env not set") }
c, err := net.DialTimeout("tcp", os.Getenv("CC_CONNECT_AGY_PERMISSION_ADDR"), 5*time.Second)
if err != nil { log.Fatal("bridge not reachable: ", err) } Type guard
func hasLiveBridge(addr string) bool { c, err := net.DialTimeout("tcp", addr, 5*time.Second); if err != nil { return false }; _ = c.Close(); return true } Try / catch
decision, err := antigravityhook.Relay(in, out, addr, token)
if err != nil {
var netErr net.Error
if errors.As(err, &netErr) { /* retry dial or fail closed */ }
return fmt.Errorf("permission relay: %w", err)
} Prevention
- Keep the cc-connect bridge session alive while agent permission hooks are pending
- Monitor bridge listener health and log dial/read failures on the server side
- Keep bridge responses well under the 64 KiB limit
- Treat relay errors as deny (fail closed) and alert instead of retrying indefinitely
When it happens
Trigger: Relay() calls json.NewDecoder(io.LimitReader(conn, 64<<10)).Decode(&response) after dialing the bridge address; the decode fails when the bridge process exited before replying, the socket closed mid-write, a non-JSON payload arrives on the CC_CONNECT_AGY_PERMISSION_ADDR socket, or the response exceeds 64 KiB.
Common situations: The cc-connect session owning the bridge crashed or was restarted while an Antigravity permission hook was pending; a stale hook fired against an old/dead bridge port; another service is listening on the address and returns a non-JSON HTTP response.
Related errors
- send permission request: %w
- decode response: %w
- decode response: %w
- poll decode: %w
- wecom: decode send response: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/7b21b6ccb1fa4a4c.
Report an issue: GitHub.