{"record":{"id":"4595a3b3520b3d69","repo":"chenhg5/cc-connect","slug":"chmod-w-4595a3","errorCode":null,"errorMessage":"chmod: %w","messagePattern":"chmod: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/updater.go","lineNumber":271,"sourceCode":"\t}\n\n\tdir := filepath.Dir(execPath)\n\ttmpFile, err := os.CreateTemp(dir, \"cc-connect-update-*\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"create temp file: %w\", err)\n\t}\n\ttmpPath := tmpFile.Name()\n\n\tif _, err := tmpFile.Write(newBinary); err != nil {\n\t\ttmpFile.Close()\n\t\tos.Remove(tmpPath)\n\t\treturn fmt.Errorf(\"write new binary: %w\", err)\n\t}\n\ttmpFile.Close()\n\n\tif err := os.Chmod(tmpPath, 0o755); err != nil {\n\t\tos.Remove(tmpPath)\n\t\treturn fmt.Errorf(\"chmod: %w\", err)\n\t}\n\n\toldPath := execPath + \".old\"\n\tos.Remove(oldPath)\n\n\tif err := os.Rename(execPath, oldPath); err != nil {\n\t\tos.Remove(tmpPath)\n\t\treturn fmt.Errorf(\"backup old binary: %w\", err)\n\t}\n\n\tif err := os.Rename(tmpPath, execPath); err != nil {\n\t\t// Try to restore\n\t\tif restoreErr := os.Rename(oldPath, execPath); restoreErr != nil {\n\t\t\tslog.Error(\"updater: failed to restore old binary after install failed\", \"error\", restoreErr)\n\t\t}\n\t\treturn fmt.Errorf(\"install new binary: %w\", err)\n\t}\n","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/updater.go#L253-L289","documentation":"The temp file must be marked executable, so replaceBinary runs os.Chmod(tmpPath, 0o755); failure (after cleanup) is wrapped as \"chmod: %w\". Without this, the staged binary could not be executed after the swap.","triggerScenarios":"SelfUpdate -> replaceBinary: os.Chmod failed on the freshly created temp file — file owned by another user (unusual), filesystem does not support permission changes (some FUSE/mounts, FAT/exFAT drives), or ACL/immutable attributes interfere.","commonSituations":"Binary directory on a USB/exFAT/FAT32 mount without POSIX permissions; FUSE filesystem (e.g. some network mounts) rejecting chmod; security software or MAC policies (SELinux) denying the operation; immutable attribute inherited from the directory.","solutions":["Move the cc-connect installation to a filesystem with POSIX permission support (ext4/xfs/APFS), not FAT/exFAT.","Check SELinux/AppArmor denials (ausearch -m avc) and add allow rules or set permissive mode while updating.","Remove immutable attributes: sudo chattr -i <path> if set.","Since the temp file was just created by the same process, failure here is rare — verify ownership with ls -l on the temp leftovers (none should exist; the updater cleans up) and directory mount options.","Retry the update after fixing the mount/policy; the updater removes the temp file on failure so no stale artifacts remain."],"exampleFix":"# before: install dir on exFAT USB mount\n/opt/usb/cc-connect (mount -t exfat) -> chmod: operation not permitted\n# after\nsudo mv /opt/usb/cc-connect /opt/cc-connect && /opt/cc-connect/cc-connect update","handlingStrategy":"validation","validationCode":"var st syscall.Statfs_t\nif err := syscall.Statfs(installDir, &st); err == nil {\n    if st.Flags&unix.ST_NOSUID != 0 || isFAT(exoticMount) {\n        return fmt.Errorf(\"filesystem %d may not support chmod\", st.Flags)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := selfUpdate(); err != nil {\n    if strings.Contains(err.Error(), \"chmod\") {\n        // move installation to a POSIX-permission filesystem and retry\n    }\n}","preventionTips":["Install on ext4/xfs/APFS, not FAT/exFAT/FUSE mounts","Check SELinux/AppArmor audit logs if chmod fails unexpectedly","Avoid chattr +i on install directories"],"tags":["filesystem","permissions","chmod","self-update"],"backgroundTag":"file-write-permission-denied","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"}