{"record":{"id":"ef1bd02207e25c78","repo":"chenhg5/cc-connect","slug":"write-plist-w","errorCode":null,"errorMessage":"write plist: %w","messagePattern":"write plist: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"daemon/launchd.go","lineNumber":64,"sourceCode":"\t\treturn fmt.Errorf(\"create LaunchAgents dir: %w\", err)\n\t}\n\tif err := os.MkdirAll(filepath.Dir(cfg.LogFile), 0755); err != nil {\n\t\treturn fmt.Errorf(\"create log dir: %w\", err)\n\t}\n\n\t// Unload existing service first (ignore errors) so we do not leave a stale\n\t// job behind when switching between GUI and headless sessions.\n\tbootoutLaunchdTargets()\n\n\tplist := buildPlist(cfg)\n\t// 0600: plist may contain captured secret values (config.toml ${ENV}\n\t// placeholders and any EnvDiscoverer extension output). User-only\n\t// LaunchAgents path; root can still read but that is the user's own\n\t// machine boundary. os.WriteFile only applies perm on create, so\n\t// Chmod afterwards is required to harden reinstalls of files that\n\t// pre-existed at 0644 from earlier cc-connect versions.\n\tif err := os.WriteFile(plistPath, []byte(plist), 0600); err != nil {\n\t\treturn fmt.Errorf(\"write plist: %w\", err)\n\t}\n\tif err := os.Chmod(plistPath, 0600); err != nil {\n\t\treturn fmt.Errorf(\"chmod plist: %w\", err)\n\t}\n\n\tdomain := preferredLaunchdDomain()\n\tif out, err := runLaunchctl(\"bootstrap\", domain, plistPath); err != nil {\n\t\treturn fmt.Errorf(\"launchctl bootstrap: %s (%w)\", out, err)\n\t}\n\n\tif _, err := runLaunchctl(\"kickstart\", \"-kp\", launchdTarget(domain)); err != nil {\n\t\treturn fmt.Errorf(\"launchctl kickstart: %w\", err)\n\t}\n\treturn nil\n}\n\nfunc (m *launchdManager) Uninstall() error {\n\tbootoutLaunchdTargets()","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/daemon/launchd.go#L46-L82","documentation":"After building the launchd plist, Install writes it to the LaunchAgents path with os.WriteFile at 0600 and then chmods to 0600 (since WriteFile only applies perm on create). A failure writing the file is wrapped as 'write plist:'. This is the final persistence step for the service definition, so install aborts without registering the job.","triggerScenarios":"os.WriteFile(plistPath, plist, 0600) fails — disk full, permission denied on an existing plist owned by another user, read-only volume, or the LaunchAgents path became unwritable between mkdir and write.","commonSituations":"An old plist created by root that the current user cannot overwrite; quota/disk-full; antivirus blocking writes into LaunchAgents; installing as a different user than the previous install.","solutions":["Check ownership of the existing plist and chown/remove it: ls -l ~/Library/LaunchAgents/<plist>; sudo rm if owned by root","Free disk space if the cause is ENOSPC","Re-run install as the same user that owns the LaunchAgents directory","Apply the wrapped %w cause (os error) to identify permission vs. space issues"],"exampleFix":"// before\n$ cc-connect daemon install  // plist owned by root\n// after\n$ sudo rm ~/Library/LaunchAgents/com.cc-connect.plist\n$ cc-connect daemon install","handlingStrategy":"try-catch","validationCode":"if st, err := os.Stat(plistPath); err == nil {\n    if fi, _ := st.Info(); fi != nil && !isOwnedByCurrentUser(fi) {\n        return fmt.Errorf(\"plist %s not owned by current user\", plistPath)\n    }\n}\nif err := unix.Access(filepath.Dir(plistPath), unix.W_OK); err != nil {\n    return fmt.Errorf(\"LaunchAgents dir not writable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := daemon.Install(cfg); err != nil {\n    var pe *fs.PathError\n    if errors.As(err, &pe) && errors.Is(pe.Err, os.ErrPermission) {\n        // chown/remove the stale plist, then retry install\n    }\n    return err\n}","preventionTips":["Always install as the same user; never mix sudo and user installs","Keep disk space above a safety margin (ENOSPC breaks WriteFile)","Check existing plist ownership/permissions before reinstalling"],"tags":["filesystem","launchd","install","plist"],"backgroundTag":"file-write-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"}