[BUG] Claude Code fails with EACCES on multi-user systems when /tmp/claude is not writable

Resolved 💬 5 comments Opened Jan 22, 2026 by noor01 Closed Mar 11, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Claude Code fails with EACCES on multi-user systems when /tmp/claude is not writable

Environment

  • OS: Linux (Ubuntu/Debian-based cluster)
  • Claude Code Version: 2.1.15 (linux-x64)
  • Installation method: VS Code extension
  • Environment type: Shared academic/research computing cluster with multiple users

Relevant environment variables:

TMPDIR=/tmp/user/457296
TEMPDIR=/tmp/user/457296
TMP=/tmp/user/457296
TEMP=/tmp/user/457296

File system state:

$ ls -ld /tmp
drwxrwxrwt 34 root root 4096 Jan 22 10:40 /tmp

$ ls -ld /tmp/claude
drwxr-xr-x 9 user2 operator 4096 Jan 15 23:35 /tmp/claude

$ whoami
user1

* user2 is another user. user1 is me. usernames changed for privacy

$ id
uid=457296(user1) gid=37(operator) groups=37(operator)

Problem Description

Claude Code attempts to create workspace-specific cache directories in /tmp/claude/ regardless of the TMPDIR environment variable setting. When /tmp/claude/ is owned by another user with restrictive permissions (755), Claude Code fails with an EACCES permission error.

This is a common scenario on shared computing clusters where:

  1. Multiple users run Claude Code
  2. The first user to run Claude Code creates /tmp/claude/ with their default umask (typically 755)
  3. Subsequent users cannot write to this directory even if they're in the same group

Actual Behavior

Error: EACCES: permission denied, mkdir '/tmp/claude/-path-to-project'

The error occurs when Claude Code tries to create a workspace-specific subdirectory in /tmp/claude/ by transforming the working directory path (e.g., /university_cluster/users/user1/projects/project1/tmp/claude/-university_cluster-user1-projects-project1).

Examples of failed operations:

  • Running Python scripts: python main.py configs/config.yaml
  • Spawning Task tool agents
  • Any operation requiring workspace cache

What Should Happen?

Expected Behavior

Claude Code should handle temporary directories in one of these ways:

Option 1: Respect TMPDIR (Preferred)

When TMPDIR is set, use $TMPDIR/claude/ instead of hardcoded /tmp/claude/:

TMPDIR=/tmp/user/457296 → Use /tmp/user/457296/claude/-path-to-project

Option 2: Graceful fallback

If /tmp/claude/ is not writable, fall back to:

  1. $TMPDIR/claude/ if TMPDIR is set
  2. $HOME/.cache/claude/ as a last resort

Option 3: User-specific directories by default

Always use user-specific paths to avoid multi-user conflicts:

/tmp/claude-${USER}/-path-to-project
or
${TMPDIR:-/tmp}/claude/${USER}/-path-to-project

Additional Context

Observed behavior:

  • Claude Code successfully creates user-specific session files in $TMPDIR/claude/ (e.g., /tmp/user/457296/claude/)
  • However, workspace caches are hardcoded to /tmp/claude/ regardless of TMPDIR
  • This inconsistency suggests the codebase uses different temp directory resolution in different modules

Current workarounds:

  1. Administrator runs: sudo chmod 1777 /tmp/claude (sticky bit like /tmp)
  2. First user runs: chmod 775 /tmp/claude (if they remember)
  3. Each user creates their own directory: mkdir ~/tmp/claude && ln -s ~/tmp/claude /tmp/claude-${USER} (doesn't fix the issue)

All workarounds are suboptimal and require knowledge of the internals.

Suggested Fix

The temp directory resolution should follow this precedence:

function getClaudeWorkspaceTmpDir(workspacePath) {
  const baseTmpDir = process.env.TMPDIR ||
                     process.env.TMP ||
                     process.env.TEMP ||
                     '/tmp';

  const claudeDir = path.join(baseTmpDir, 'claude');

  // Try to use shared directory, fall back to user-specific
  try {
    fs.mkdirSync(claudeDir, { recursive: true });
  } catch (err) {
    if (err.code === 'EACCES' || err.code === 'EPERM') {
      // Fall back to user-specific directory
      const userClaudeDir = path.join(os.homedir(), '.cache', 'claude');
      return path.join(userClaudeDir, sanitizeWorkspacePath(workspacePath));
    }
    throw err;
  }

  return path.join(claudeDir, sanitizeWorkspacePath(workspacePath));
}

Related Issues

This may be related to general temp directory handling in Claude Code. Consider auditing all temp directory creation to ensure consistent behavior across the codebase.

System Information

$ uname -a
Linux 5.15.0-116-generic

$ ls -la /tmp/user/457296/claude/
# Successfully creates files here - this works correctly

$ env | grep -i tmp
TEMPDIR=/tmp/user/457296
TMPDIR=/tmp/user/457296
TMP=/tmp/user/457296
TEMP=/tmp/user/457296

$ claude --version
2.1.15

---

Error Messages/Logs

Steps to Reproduce

Steps to Reproduce

  1. On a multi-user Linux system, have User A run Claude Code, which creates /tmp/claude/ with permissions drwxr-xr-x (755)
  2. As User B (different user, same group), set environment variables:

``bash
export TMPDIR=/tmp/user/$(id -u)
export TMP=$TMPDIR
export TEMP=$TMPDIR
``

  1. Launch Claude Code from a project directory (e.g., /path/to/project)
  2. Attempt to run any command that triggers Claude Code's workspace cache

Claude Model

Sonnet (default)

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.15

Platform

Anthropic API

Operating System

Ubuntu/Debian Linux

Terminal/Shell

VS Code integrated terminal

Additional Information

_No response_

View original on GitHub ↗

This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗