chenhg5/cc-connect · error
resolve home dir: %w
Error message
resolve home dir: %w
What it means
saveAttachment calls os.UserHomeDir() and wraps its failure as "resolve home dir: %w". os.UserHomeDir returns an error when neither $HOME (Unix) nor the Windows user-profile APIs yield a home directory, so the platform cannot compute ~/.cc-connect/attachments and the attachment save aborts.
Source
Thrown at platform/wps-agentspace/wpsagentspace.go:269
name = "image_" + time.Now().Format("20060102_150405") + ext
}
path, err := p.saveAttachment(name, img.Data)
if err != nil {
return fmt.Errorf("wps-agentspace: SendImage: %w", err)
}
notice := fmt.Sprintf("🖼 图片已保存到本地:\n%s", path)
return p.sendText(rc.ChatID, notice, rc)
}
// saveAttachment writes data to ~/.cc-connect/attachments/<name> and returns
// the absolute path. The filename is sanitized to a basename to prevent path
// traversal.
func (p *Platform) saveAttachment(name string, data []byte) (string, error) {
home, err := os.UserHomeDir()
if err != nil {
return "", fmt.Errorf("resolve home dir: %w", err)
}
dir := filepath.Join(home, ".cc-connect", "attachments")
if err := os.MkdirAll(dir, 0o755); err != nil {
return "", fmt.Errorf("mkdir: %w", err)
}
name = filepath.Base(name)
if name == "" || name == "." || name == "/" {
name = fmt.Sprintf("file_%d", time.Now().UnixMilli())
}
path := filepath.Join(dir, name)
if err := os.WriteFile(path, data, 0o644); err != nil {
return "", fmt.Errorf("write: %w", err)
}
return path, nil
}
// Stop gracefully shuts down the platform.View on GitHub (pinned to 4000b2338a)
Solutions
- Set HOME explicitly in the service environment (systemd: Environment=HOME=/home/ccconnect or /var/lib/cc-connect; docker: -e HOME=/home/app).
- Run the daemon as a regular user that has a home directory, or create one with useradd -m.
- As a caller, pre-check home resolution and fail fast with a clear config error before starting the platform.
Example fix
// before: launching daemon with scrubbed env
cmd := exec.Command("cc-connect")
cmd.Env = []string{"PATH=/usr/bin"}
// after
cmd := exec.Command("cc-connect")
cmd.Env = append(os.Environ(), "HOME=/var/lib/cc-connect") Defensive patterns
Strategy: validation
Validate before calling
home, err := os.UserHomeDir()
if err != nil || home == "" {
return errors.New("HOME is not set; configure HOME for the cc-connect process")
}
if fi, err := os.Stat(home); err != nil || !fi.IsDir() {
return fmt.Errorf("HOME %s is not an existing directory", home)
} Try / catch
if _, err := p.SendFile(rc, file); err != nil && strings.Contains(err.Error(), "resolve home dir") {
slog.Error("fix environment: set HOME for the daemon user", "err", err)
} Prevention
- Set Environment=HOME=... in systemd units or export HOME in container/cron entrypoints.
- Avoid scrubbing os.Environ() when spawning the daemon.
- On Windows service accounts, verify a user profile is loaded before starting the platform.
- Add a startup self-check that fails fast if os.UserHomeDir() errors.
When it happens
Trigger: Any call to SendFile or SendImage while the process has no resolvable home directory: $HOME unset/empty on Unix, or the Windows profile lookup failing (e.g. unusual service accounts).
Common situations: Daemonizing via systemd/init without setting HOME; running under docker with HOME unset or set to /nonexistent; running as a Windows service account without a loaded profile; launching from a stripped cron environment.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- resolve home directory for Agy permission bridge: %w
- resolve home directory: %w
- resolve home directory: %w
- pi: cannot determine settings path
- cannot resolve home directory: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/f5f6a77a2f8d444f.
Report an issue: GitHub.