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

  1. Check the wrapped error to identify the failing filesystem; if on Windows, confirm this build supports the Chmod path used here.
  2. Use a different temp directory (TMPDIR/os.TempDir override) on a local filesystem that supports chmod.
  3. If using run_as_user, ensure TMPDIR is set to a world-traversable path like /tmp instead of a private user cache dir.
  4. 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

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


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