{"record":{"id":"966aeb78e1e4ccf4","repo":"chenhg5/cc-connect","slug":"marshal-agy-hooks-overlay-w","errorCode":null,"errorMessage":"marshal Agy hooks overlay: %w","messagePattern":"marshal Agy hooks overlay: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agent/antigravity/permission_bridge.go","lineNumber":157,"sourceCode":"\t\t\t\t\"matcher\": \"*\",\n\t\t\t\t\"hooks\": []any{\n\t\t\t\t\tmap[string]any{\n\t\t\t\t\t\t\"type\":    \"command\",\n\t\t\t\t\t\t\"command\": shellQuote(executable) + \" _agy-permission-hook\",\n\t\t\t\t\t\t\"timeout\": 86400,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t})\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"marshal Agy permission hook: %w\", err)\n\t}\n\thooks[agyPermissionHookName] = bridgeHook\n\n\tdata, err := json.MarshalIndent(hooks, \"\", \"  \")\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"marshal Agy hooks overlay: %w\", err)\n\t}\n\tdata = append(data, '\\n')\n\tif err := os.WriteFile(filepath.Join(overlayConfigDir, \"hooks.json\"), data, 0o600); err != nil {\n\t\treturn \"\", fmt.Errorf(\"write Agy hooks overlay: %w\", err)\n\t}\n\treturn overlayConfigRoot, nil\n}\n\nfunc mirrorDirectoryEntries(sourceDir, targetDir string, skip map[string]bool) error {\n\tentries, err := os.ReadDir(sourceDir)\n\tif os.IsNotExist(err) {\n\t\treturn nil\n\t}\n\tif err != nil {\n\t\treturn fmt.Errorf(\"read Agy config directory %s: %w\", sourceDir, err)\n\t}\n\tfor _, entry := range entries {\n\t\tif skip[entry.Name()] {","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/agent/antigravity/permission_bridge.go#L139-L175","documentation":"After merging existing hooks with the bridge hook, createAgyConfigOverlay serializes the full hooks map with json.MarshalIndent to write the overlay hooks.json. If marshaling fails, this wrapped error is returned.","triggerScenarios":"newAgyPermissionBridge → createAgyConfigOverlay when json.MarshalIndent(hooks) fails — typically because an existing hook entry loaded from ~/.gemini/config/hooks.json (stored as json.RawMessage) is invalid or contains values that cannot be re-marshaled.","commonSituations":"A hand-crafted hooks.json containing entries with unsupported values (e.g. NaN-like tokens from other tooling, or corrupted RawMessage content) that fail re-serialization.","solutions":["Validate and fix the original ~/.gemini/config/hooks.json so every entry is well-formed JSON.","Temporarily rename the real hooks.json and retry session start to confirm the existing content is the culprit.","Remove the offending hook entry and re-add it in valid JSON form.","Rebuild cc-connect if running a modified build with altered hook structures."],"exampleFix":"// before: hooks.json entry that can't re-marshal\n{\"myHook\": \"{unclosed\"}\n// after\n{\"myHook\": {\"command\": \"/usr/bin/hook\"}}","handlingStrategy":"validation","validationCode":"// shell: ensure every existing hook entry is valid JSON before starting\npython3 - <<'EOF'\nimport json,os\np=os.path.expanduser('~/.gemini/config/hooks.json')\nh=json.load(open(p))\nassert isinstance(h, dict)\nfor k,v in h.items(): json.dumps(json.loads(json.dumps(v)))\nEOF","typeGuard":null,"tryCatchPattern":"if err := startAntigravitySession(); err != nil && strings.Contains(err.Error(), \"marshal Agy hooks overlay\") {\n    // identify the offending hook entry, fix or drop it, retry\n}","preventionTips":["Keep hook entries as plain JSON objects with primitive values.","Validate hooks.json after any external tool writes to it.","Re-generate hooks from known-good templates instead of hand-edits."],"tags":["json","marshal","config","antigravity","go"],"backgroundTag":"json-serialization-failed","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"}