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

  1. Restart the cc-connect session that owns the permission bridge, then re-run the agent operation that triggered the hook
  2. Verify CC_CONNECT_AGY_PERMISSION_ADDR points to the live bridge socket and that no other process has claimed that port
  3. Check cc-connect logs for a bridge listener crash (e.g. panics in the permission handler) and fix the underlying crash
  4. 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

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


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/7b21b6ccb1fa4a4c. Report an issue: GitHub.