{"record":{"id":"479078182f649cd1","repo":"chenhg5/cc-connect","slug":"link-agy-config-s-w","errorCode":null,"errorMessage":"link Agy config %s: %w","messagePattern":"link Agy config (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agent/antigravity/permission_bridge.go","lineNumber":181,"sourceCode":"\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()] {\n\t\t\tcontinue\n\t\t}\n\t\tsource := filepath.Join(sourceDir, entry.Name())\n\t\ttarget := filepath.Join(targetDir, entry.Name())\n\t\tif err := os.Symlink(source, target); err != nil {\n\t\t\treturn fmt.Errorf(\"link Agy config %s: %w\", source, err)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc shellQuote(value string) string {\n\treturn \"'\" + strings.ReplaceAll(value, \"'\", \"'\\\"'\\\"'\") + \"'\"\n}\n\nfunc bridgeTokenEqual(got, want string) bool {\n\tif len(got) != len(want) {\n\t\treturn false\n\t}\n\treturn subtle.ConstantTimeCompare([]byte(got), []byte(want)) == 1\n}\n\nfunc (b *agyPermissionBridge) Env() []string {\n\treturn []string{","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/agent/antigravity/permission_bridge.go#L163-L199","documentation":"mirrorDirectoryEntries wraps errors from os.Symlink when linking each entry from the source config directory into the overlay target directory. It is thrown when creating a symlink fails — most commonly because the target name already exists (symlinks are not created over existing entries), or because the filesystem does not support symlinks.","triggerScenarios":"createAgyConfigOverlay calls mirrorDirectoryEntries on a target dir that already contains an entry with the same name; running on a platform/filesystem without symlink support (e.g. Windows without privilege, some FAT/network mounts).","commonSituations":"A previous run crashed leaving a partially populated overlay directory; two cc-connect instances racing to build the same overlay; Windows dev environments lacking symlink privileges.","solutions":["Remove the stale overlay target directory so it can be rebuilt: rm -rf <targetDir> then rerun.","Ensure only one cc-connect instance runs at a time to avoid symlink races.","On Windows, run with Developer Mode / symlink privilege enabled, or move the overlay to an NTFS volume.","Check the wrapped cause in the message for EEXIST vs EPERM to distinguish stale-overlay from unsupported-symlink."],"exampleFix":"// before (stale overlay)\n$ ls overlay/\nsettings.json   <- leftover\n// after\n$ rm -rf overlay/ && cc-connect  # rebuilds symlinks cleanly","handlingStrategy":"validation","validationCode":"if entries, err := os.ReadDir(targetDir); err == nil && len(entries) > 0 {\n    // stale overlay — remove it before rebuilding\n    os.RemoveAll(targetDir)\n}","typeGuard":null,"tryCatchPattern":"if err := mirrorDirectoryEntries(src, dst, skip); err != nil && strings.Contains(err.Error(), \"link Agy config\") {\n    os.RemoveAll(dst)\n    // retry once\n}","preventionTips":["Always build the overlay into a fresh temp directory, then swap atomically.","Ensure only one cc-connect instance manages a given overlay.","On Windows, enable Developer Mode or use junctions/copies instead of symlinks."],"tags":["go","filesystem","symlink","antigravity"],"backgroundTag":"file-already-exists","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"}