chenhg5/cc-connect · error
write unit file: %w
Error message
write unit file: %w
What it means
Install() wraps os.WriteFile failure when writing the generated .service unit to unitPath. The unit may contain secrets, so it is written 0600; a failed write means the unit could not be persisted (permissions, read-only fs, or the path is a directory).
Source
Thrown at daemon/systemd.go:70
unitPath := m.unitPath()
if err := os.MkdirAll(filepath.Dir(unitPath), 0755); err != nil {
return fmt.Errorf("create systemd dir: %w", err)
}
if err := os.MkdirAll(filepath.Dir(cfg.LogFile), 0755); err != nil {
return fmt.Errorf("create log dir: %w", err)
}
unit := m.buildUnit(cfg)
// 0600: unit file may contain captured secret values (config.toml ${ENV}
// placeholders and any EnvDiscoverer extension output). For system-level
// units (/etc/systemd/system/) the file is owned by root and remains
// readable by root only; for user-level units under
// ~/.config/systemd/user it remains owner-only. WriteFile only applies
// perm on create, so Chmod afterwards is required to harden reinstalls
// of pre-existing 0644 units from earlier cc-connect versions.
if err := os.WriteFile(unitPath, []byte(unit), 0600); err != nil {
return fmt.Errorf("write unit file: %w", err)
}
if err := os.Chmod(unitPath, 0600); err != nil {
return fmt.Errorf("chmod unit file: %w", err)
}
for _, cmdArgs := range [][]string{
m.sysArgs("daemon-reload"),
m.sysArgs("enable", systemdServiceName),
m.sysArgs("restart", systemdServiceName),
} {
if out, err := runSystemctl(cmdArgs...); err != nil {
return fmt.Errorf("systemctl %s: %s (%w)", strings.Join(cmdArgs, " "), out, err)
}
}
return nil
}
View on GitHub (pinned to 4000b2338a)
Solutions
- Run with sudo for system-level units.
- Ensure unitPath is not a directory: `ls -ld /etc/systemd/system/cc-connect.service`.
- Check free disk space and mount status (`df -h`, `mount`).
- Verify no security module (SELinux) denies the write; check `ausearch -m avc`.
Example fix
// before
cmd.Exec("cc-connect install") // as non-root: write unit file: permission denied
// after
cmd.Exec("sudo cc-connect install") Defensive patterns
Strategy: validation
Validate before calling
unitPath := mgr.unitPath()
if fi, err := os.Stat(unitPath); err == nil && fi.IsDir() {
return fmt.Errorf("%s is a directory", unitPath)
}
probe, err := os.CreateTemp(filepath.Dir(unitPath), ".ccprobe")
if err != nil {
return fmt.Errorf("unit dir not writable: %w", err)
}
probe.Close(); os.Remove(probe.Name()) Type guard
func canCreateFile(dir string) bool {
f, err := os.CreateTemp(dir, ".probe")
if err != nil { return false }
f.Close(); os.Remove(f.Name())
return true
} Try / catch
if err := mgr.Install(cfg); err != nil {
var pe *fs.PathError
if errors.As(err, &pe) && errors.Is(pe.Err, fs.ErrPermission) {
return fmt.Errorf("run with sudo: %w", err)
}
return err
} Prevention
- Verify write access to /etc/systemd/system before system installs.
- Ensure no directory occupies the unit file path.
- Check disk space (df -h) on machines with small root volumes.
- On SELinux systems, check AVC denials if writes to /etc fail.
When it happens
Trigger: Calling Install when the unit directory exists but is not writable (system install without root), the unit path is a directory, or the disk is full/read-only.
Common situations: Non-root user running system install; SELinux/apparmor denying writes to /etc/systemd/system; unit left in a corrupted state by a previous failed install.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- create systemd dir: %w
- remove unit: %w
- read existing Agy hooks %s: %w
- kimi: read sessions dir: %w
- create run dir: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/4a8c878f31da9583.
Report an issue: GitHub.