chenhg5/cc-connect · error

create log dir: %w

Error message

create log dir: %w

What it means

Install() wraps os.MkdirAll failure for the configured log file's parent directory. It means cfg.LogFile's directory could not be created, so the service would have nowhere to write logs. This is a config-driven path, so bad configuration is the usual cause.

Source

Thrown at daemon/systemd.go:58

	}
	return &systemdManager{system: false}, nil
}

func (m *systemdManager) Platform() string {
	if m.system {
		return "systemd (system)"
	}
	return "systemd (user)"
}

func (m *systemdManager) Install(cfg Config) error {
	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{

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Fix log_file in config.toml to a writable absolute path (expand ~ yourself).
  2. Pre-create the directory with correct permissions: `sudo mkdir -p /var/log/cc-connect`.
  3. Run with elevated privileges if the log path requires root.
  4. Point LogFile at the user's home directory for user-level installs.

Example fix

// before
cfg := Config{LogFile: "/var/log/cc-connect/cc.log"} // non-root cannot mkdir /var/log/cc-connect
// after
home, _ := os.UserHomeDir()
cfg := Config{LogFile: filepath.Join(home, ".local", "state", "cc-connect", "cc.log")}
Defensive patterns

Strategy: validation

Validate before calling

logDir := filepath.Dir(cfg.LogFile)
if logDir == "" || logDir == "." {
    return fmt.Errorf("LogFile must be an absolute path")
}
if err := os.MkdirAll(logDir, 0755); err != nil {
    return fmt.Errorf("log dir not creatable: %w", err)
}
f, err := os.OpenFile(cfg.LogFile, os.O_APPEND|os.O_CREATE, 0600)
if err == nil { f.Close() }

Type guard

func logPathWritable(p string) bool {
    dir := filepath.Dir(p)
    if err := os.MkdirAll(dir, 0755); err != nil { return false }
    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 {
    if strings.Contains(err.Error(), "create log dir") {
        return fmt.Errorf("fix log_file in config.toml: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling Install with a Config whose LogFile points into an unwritable or malformed location: non-existent parent under a read-only mount, a file occupying the parent path, or an empty/invalid LogFile path.

Common situations: config.toml sets log_file to /var/log/cc-connect/cc.log but the user lacks root; a typo like log_file = "~/cc.log" evaluated with an unexpanded '~'; log dir deleted on a tmpfs after reboot.

Understand the failure class

Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/38eb1654c189fd4a. Report an issue: GitHub.