{"record":{"id":"4ac93f8f4d1c3839","repo":"chenhg5/cc-connect","slug":"invalid-permission-decision-q","errorCode":null,"errorMessage":"invalid permission decision %q","messagePattern":"invalid permission decision %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agent/antigravityhook/protocol.go","lineNumber":68,"sourceCode":"\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)\n\t}\n\n\tif err := json.NewEncoder(out).Encode(response); err != nil {\n\t\treturn fmt.Errorf(\"write hook response: %w\", err)\n\t}\n\treturn nil\n}\n","sourceCodeStart":50,"sourceCodeEnd":76,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/agent/antigravityhook/protocol.go#L50-L76","documentation":"After decoding a BridgeResponse, Relay validates that the decision field is exactly \"allow\" or \"deny\". This error is thrown when the bridge returned a decision value outside that enum (including an empty string when a malformed/truncated JSON object decoded with zeroed fields). It protects the hook protocol so only unambiguous decisions are forwarded to Antigravity.","triggerScenarios":"The bridge peer on CC_CONNECT_AGY_PERMISSION_ADDR sends a JSON object whose \"decision\" is not \"allow\" or \"deny\" — e.g. an error payload like {\"error\":\"...\"}, an empty JSON object {} (decision decodes to \"\"), or a bridge implementation using different decision vocabulary.","commonSituations":"Version mismatch between the hook binary and the cc-connect bridge (bridge protocol changed); the bridge answered with an error object instead of a decision; a third-party service occupying the port returns its own JSON shape.","solutions":["Upgrade the antigravityhook binary and cc-connect to matching versions so the bridge response schema is aligned","Inspect what the bridge actually returned (log the raw response before validation) to identify the unexpected decision value","Check whether the bridge hit an internal error and replied with a non-decision payload; fix that error first","Ensure no unrelated service is bound to the CC_CONNECT_AGY_PERMISSION_ADDR port echoing foreign JSON"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"var resp BridgeResponse\nif err := json.Unmarshal(raw, &resp); err != nil { return err }\nif resp.Decision != \"allow\" && resp.Decision != \"deny\" { return fmt.Errorf(\"bad decision %q\", resp.Decision) }","typeGuard":"func validDecision(d string) bool { return d == \"allow\" || d == \"deny\" }","tryCatchPattern":"if err := Relay(in, out, addr, token); err != nil {\n    if strings.Contains(err.Error(), \"invalid permission decision\") {\n        log.Error(\"bridge returned malformed decision — check version compatibility\", \"err\", err)\n    }\n    return err\n}","preventionTips":["Keep hook binary and cc-connect versions in lockstep","On the bridge side, always emit {\"decision\":\"allow\"|\"deny\"} even on internal errors","Reject non-decision payloads early in bridge code with clear server logs","Pin/verify no other service binds the bridge port"],"tags":["validation","ipc","protocol"],"backgroundTag":"invalid-enum-value","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}