chenhg5/cc-connect · error
claudecode: chmod per-spawn prompt file 0o644: %w
Error message
claudecode: chmod per-spawn prompt file 0o644: %w
What it means
writeTempAppendPromptFile (agent/claudecode/session.go:159) creates a per-spawn temp file holding the append system prompt, and calls f.Chmod(0o644) so non-owner users (e.g. a run_as_user target) can read it — mirroring the shared prompt file's mode. If the Chmod syscall fails, it closes and removes the temp file and returns 'claudecode: chmod per-spawn prompt file 0o644: %w'.
Source
Thrown at agent/claudecode/session.go:159
if err != nil {
return "", err
}
if _, err := f.WriteString(content); err != nil {
_ = f.Close()
_ = os.Remove(f.Name())
return "", err
}
// os.CreateTemp defaults to mode 0600 owned by the cc-connect process
// user (often root when launched by systemd). When the agent is spawned
// under run_as_user, the target user is different and gets EACCES on
// 0600 root-owned files (issue #1429). The shared prompt file already
// uses 0o644 (see ensureSharedSystemPromptFile → writeFileAtomic);
// the per-spawn temp file is just a superset of the shared content
// and is equally non-secret, so we mirror that mode here.
if err := f.Chmod(0o644); err != nil {
_ = f.Close()
_ = os.Remove(f.Name())
return "", fmt.Errorf("claudecode: chmod per-spawn prompt file 0o644: %w", err)
}
if err := f.Close(); err != nil {
_ = os.Remove(f.Name())
return "", err
}
return f.Name(), nil
}
// writeFileAtomic writes data to path via a temp file + rename, so a
// crash mid-write does not leave a half-written prompt file that the
// next spawn would mistake for valid content.
func writeFileAtomic(path string, data []byte, perm os.FileMode) error {
dir := filepath.Dir(path)
f, err := os.CreateTemp(dir, ".cc-connect-system-*.tmp")
if err != nil {
return err
}
tmp := f.Name()View on GitHub (pinned to 4000b2338a)
Solutions
- Check the wrapped error to identify the failing filesystem; if on Windows, confirm this build supports the Chmod path used here.
- Use a different temp directory (TMPDIR/os.TempDir override) on a local filesystem that supports chmod.
- If using run_as_user, ensure TMPDIR is set to a world-traversable path like /tmp instead of a private user cache dir.
- Upgrade to a version where the Windows chmod path is handled or skipped; the prompt content is non-secret so relaxed modes are safe.
Example fix
// before
os.Setenv("TMPDIR", filepath.Join(homeDir, ".cache", "cc-connect"))
path, err := writeTempAppendPromptFile(ccDataDir, prompt) // chmod fails on restricted dir
// after
os.Setenv("TMPDIR", "/tmp") // local fs that supports 0644 chmod
path, err := writeTempAppendPromptFile(ccDataDir, prompt) Defensive patterns
Strategy: validation
Validate before calling
tmp := os.TempDir()
probe := filepath.Join(tmp, ".cc-probe")
if err := os.WriteFile(probe, []byte("x"), 0o644); err != nil {
return fmt.Errorf("temp dir %s not writable with 0644: %w", tmp, err)
}
os.Remove(probe) Try / catch
path, err := writeTempAppendPromptFile(ccDataDir, prompt)
if err != nil {
if runtime.GOOS == "windows" || strings.Contains(err.Error(), "chmod") {
log.Warn("chmod unsupported on this fs; ensure TMPDIR is a local volume")
}
return fmt.Errorf("prompt file setup failed: %w", err)
} Prevention
- Point TMPDIR at a local filesystem that supports POSIX modes (avoid exotic network mounts).
- On Windows, expect Chmod semantics differences; prefer builds handling that explicitly.
- When using run_as_user, ensure the temp dir is traversable by the target user (e.g. /tmp).
- Pre-startup probe: write+chmod a scratch file to validate the temp dir before spawning sessions.
When it happens
Trigger: Calling newClaudeSession (which routes through writeTempAppendPromptFile when platformPrompt/appendSystemPrompt are non-empty) on a filesystem where f.Chmod fails — e.g. Windows where os.File.Chmod has limited semantics, or temp dirs on filesystems/ACLs that reject mode changes.
Common situations: Windows builds where Chmod on an open file fails or behaves oddly; temp directory mounted with restrictive umask/ACLs; running inside containers with certain volume mounts (some network filesystems reject chmod).
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
- read existing Agy hooks %s: %w
- claudecode: create usage temp dir: %w
- session not found
- session file not found: %s
- claudeSession: ensure shared prompt file: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/ea77567a3938c310.
Report an issue: GitHub.