chenhg5/cc-connect · error

read existing Agy hooks %s: %w

Error message

read existing Agy hooks %s: %w

What it means

createAgyConfigOverlay reads ~/.gemini/config/hooks.json to merge existing hooks into the overlay. If the read fails with any error other than NotExist (permission denied, I/O error, path is a directory), this wrapped error is returned.

Source

Thrown at agent/antigravity/permission_bridge.go:129

	if err := mirrorDirectoryEntries(realConfigRoot, overlayConfigRoot, map[string]bool{"config": true}); err != nil {
		return "", err
	}
	realConfigDir := filepath.Join(realConfigRoot, "config")
	if err := mirrorDirectoryEntries(realConfigDir, overlayConfigDir, map[string]bool{"hooks.json": true}); err != nil {
		return "", err
	}

	hooks := make(map[string]json.RawMessage)
	hooksPath := filepath.Join(realConfigDir, "hooks.json")
	if data, err := os.ReadFile(hooksPath); err == nil {
		if err := json.Unmarshal(data, &hooks); err != nil {
			return "", fmt.Errorf("parse existing Agy hooks %s: %w", hooksPath, err)
		}
		if hooks == nil {
			hooks = make(map[string]json.RawMessage)
		}
	} else if !os.IsNotExist(err) {
		return "", fmt.Errorf("read existing Agy hooks %s: %w", hooksPath, err)
	}

	executable, err := os.Executable()
	if err != nil {
		return "", fmt.Errorf("resolve cc-connect executable for Agy hook: %w", err)
	}
	bridgeHook, err := json.Marshal(map[string]any{
		"PreToolUse": []any{
			map[string]any{
				"matcher": "*",
				"hooks": []any{
					map[string]any{
						"type":    "command",
						"command": shellQuote(executable) + " _agy-permission-hook",
						"timeout": 86400,
					},
				},
			},

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Check permissions: `ls -la ~/.gemini/config/hooks.json` and make it readable by the cc-connect user (chmod 600 with correct owner).
  2. If hooks.json is a directory, remove it — it should be a regular file.
  3. Verify no mandatory access control (SELinux/AppArmor) is blocking reads; restore appropriate labels/context.
  4. On network home dirs, verify the mount is healthy and the file is accessible.

Example fix

// before
-rw------- root root ~/.gemini/config/hooks.json  # cc-connect runs as ccuser
// after
chown ccuser ~/.gemini/config/hooks.json && chmod 600 ~/.gemini/config/hooks.json
Defensive patterns

Strategy: validation

Validate before calling

// shell: preflight readability of the real hooks file
[ -r "$HOME/.gemini/config/hooks.json" ] && [ -f "$HOME/.gemini/config/hooks.json" ] \
  || echo "hooks.json unreadable or a directory"

Try / catch

if err := startAntigravitySession(); err != nil && strings.Contains(err.Error(), "read existing Agy hooks") {
    // inspect ownership/permissions of ~/.gemini/config/hooks.json, fix, retry
}

Prevention

When it happens

Trigger: newAgyPermissionBridge → createAgyConfigOverlay when os.ReadFile on <home>/.gemini/config/hooks.json fails with EACCES, EISDIR, EIO, etc. (only ENOENT is tolerated).

Common situations: hooks.json owned by another user with restrictive permissions, hooks.json accidentally created as a directory, NFS/network home directories with stale handles, or SELinux/AppArmor denying read access.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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