{"record":{"id":"7faa71a5b43827b1","repo":"chenhg5/cc-connect","slug":"connect-permission-bridge-w","errorCode":null,"errorMessage":"connect permission bridge: %w","messagePattern":"connect permission bridge: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agent/antigravityhook/protocol.go","lineNumber":50,"sourceCode":"func Relay(in io.Reader, out io.Writer, address, token string) error {\n\tif strings.TrimSpace(address) == \"\" || strings.TrimSpace(token) == \"\" {\n\t\treturn fmt.Errorf(\"permission bridge environment is missing\")\n\t}\n\n\tinput, err := io.ReadAll(io.LimitReader(in, maxHookInput+1))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"read hook input: %w\", err)\n\t}\n\tif len(input) > maxHookInput {\n\t\treturn fmt.Errorf(\"hook input exceeds %d bytes\", maxHookInput)\n\t}\n\tif !json.Valid(input) {\n\t\treturn fmt.Errorf(\"hook input is not valid JSON\")\n\t}\n\n\tconn, err := net.DialTimeout(\"tcp\", address, bridgeDialTimeout)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"connect permission bridge: %w\", err)\n\t}\n\tdefer func() { _ = conn.Close() }()\n\t// The listener is started before agy runs this hook, so dial failures should\n\t// fail closed quickly. After connect, wait much longer for a human response.\n\t_ = conn.SetDeadline(time.Now().Add(bridgeResponseTimeout))\n\n\tif err := json.NewEncoder(conn).Encode(BridgeRequest{Token: token, HookInput: input}); err != nil {\n\t\treturn fmt.Errorf(\"send permission request: %w\", err)\n\t}\n\n\tvar response BridgeResponse\n\tif err := json.NewDecoder(io.LimitReader(conn, 64<<10)).Decode(&response); err != nil {\n\t\treturn fmt.Errorf(\"read permission response: %w\", err)\n\t}\n\tswitch response.Decision {\n\tcase \"allow\", \"deny\":\n\tdefault:\n\t\treturn fmt.Errorf(\"invalid permission decision %q\", response.Decision)","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/agent/antigravityhook/protocol.go#L32-L68","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\n$ CC_CONNECT_AGY_PERMISSION_ADDR=127.0.0.1:0 agy ...\n// after\n$ CC_CONNECT_AGY_PERMISSION_ADDR=127.0.0.1:47391 agy ...   # port from the live listener","handlingStrategy":"retry","validationCode":"conn, err := net.DialTimeout(\"tcp\", addr, 2*time.Second)\nif err != nil { log.Fatalf(\"bridge %s unreachable before launching agy: %v\", addr, err) }\nconn.Close()","typeGuard":null,"tryCatchPattern":"if err := Relay(...); err != nil {\n    var ne net.Error\n    if errors.As(err, &ne) || strings.HasPrefix(err.Error(), \"connect permission bridge:\") {\n        // treat as deny; optionally retry with backoff while session is alive\n    }\n}","preventionTips":["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"],"tags":["network","tcp","connection","permissions"],"backgroundTag":"connection-refused","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}