chenhg5/cc-connect · error
work_dir is not accessible: %s: %w
Error message
work_dir is not accessible: %s: %w
What it means
validateProjectWorkDir throws this when os.Stat on the work_dir fails with an error other than NotExist (e.g. permission denied on a parent directory, I/O error). The underlying OS error is wrapped with %w so errors.Is/As still work on the cause.
Source
Thrown at core/setup.go:523
}
mgmtJSON(w, http.StatusCreated, map[string]any{
"message": fmt.Sprintf("platform %q added to project %q", req.Type, projectName),
"restart_required": true,
})
}
func validateProjectWorkDir(workDir string) (string, error) {
trimmed := strings.TrimSpace(workDir)
if trimmed == "" {
return "", nil
}
info, err := os.Stat(trimmed)
if err != nil {
if os.IsNotExist(err) {
return "", fmt.Errorf("work_dir does not exist: %s", trimmed)
}
return "", fmt.Errorf("work_dir is not accessible: %s: %w", trimmed, err)
}
if !info.IsDir() {
return "", fmt.Errorf("work_dir is not a directory: %s", trimmed)
}
return trimmed, nil
}
View on GitHub (pinned to 4000b2338a)
Solutions
- Run `ls -ld` on the path and each parent to find where permission is denied; chown/chmod or move the work_dir somewhere the service user can access
- Inspect the wrapped cause with errors.Is(err, fs.ErrPermission) etc. to identify the exact OS error
- If running under systemd, add ReadWritePaths=/supplementary groups to the unit for the directory
Example fix
// before work_dir = "/root/projects/app" # service runs as cconnect // after work_dir = "/srv/projects/app" # chown cconnect:cconnect /srv/projects/app
Defensive patterns
Strategy: validation
Validate before calling
wd := strings.TrimSpace(cfg.WorkDir)
for p := wd; p != filepath.Dir(p); p = filepath.Dir(p) {
if _, err := os.Stat(p); err != nil {
return fmt.Errorf("cannot access %s: %w", p, err)
}
}
if err := unix.Access(wd, unix.W_OK); err != nil {
return fmt.Errorf("no write access to %s: %w", wd, err)
} Type guard
func canAccessDir(path string) bool {
f, err := os.Open(path)
if err != nil { return false }
defer f.Close()
if _, err := f.Readdirnames(1); err != nil && err != io.EOF { return false }
return true
} Try / catch
dir, err := validateProjectWorkDir(cfg.WorkDir)
if err != nil {
var pe *fs.PathError
if errors.As(err, &pe) && errors.Is(pe.Err, fs.ErrPermission) {
slog.Error("work_dir permission denied; run as a user with access or fix ownership", "path", pe.Path)
}
return err
} Prevention
- Run cc-connect as a user that owns (or can traverse) every project work_dir
- Avoid work_dirs under /root or other users' homes when running as a service
- Check systemd unit ReadWritePaths/ProtectHome settings that may sandbox directory access
When it happens
Trigger: Statting a path whose parent directory denies traversal permission, a path on an unmounted filesystem, a broken automount, or a dangling symlink where the link's target dir is inaccessible, during project save/detail handlers.
Common situations: work_dir under /root or another user's home while cc-connect runs as a different user; NFS/SMB mount down; sandboxed service (systemd) lacking access to the user's home directory.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- codex: mkdir codex home: %w
- codex: write config.toml: %w
- read existing Agy hooks %s: %w
- antigravity: permission responses are only available in defa
- permission bridge environment is missing
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/6070e39b26afc0a1.
Report an issue: GitHub.