Agentbrisk

Claude Code Permission Denied: Fix File Read/Write Errors

April 29, 2026 · Editorial Team · 5 min read · claude-codetroubleshootingerror-fix

You've got Claude Code running in your monorepo, you ask it to read a config file three directories deep, and it comes back with something like Error: EACCES: permission denied, open '/workspace/packages/auth/src/config.ts'. Or worse, it tries to write a fix and silently fails, leaving you with no output and no clear explanation. This happens more often than it should in monorepo setups, and the reasons are spread across a few different layers: filesystem permissions, Claude Code's own allow-list system, and sometimes symlink resolution gone wrong.

What this error actually means

Claude Code runs with the permissions of the user who launched it, but it also has its own internal permission system that controls which directories it's allowed to read from and write to. This is separate from OS-level file permissions. The EACCES error can mean either the OS denied access (a true filesystem permission problem) or Claude Code's internal trust system decided the path was out of scope.

Claude Code stores its allowed paths in ~/.claude/settings.json (user-level) or .claude/settings.json at the project root (project-level). When you run claude from a monorepo root, it doesn't automatically trust all subdirectories, especially if those packages have their own .claude/settings.json files that weren't set up correctly.

In Node.js monorepos using pnpm workspaces or yarn workspaces, symlinks inside node_modules can cause path resolution to land outside the directory Claude Code considers trusted. The resolved path might be something like /home/user/.pnpm-store/v3/files/... which Claude Code has never seen before and refuses to touch.

Quick fix (when you need it working in 60 seconds)

  1. Check what directory Claude Code was launched from: pwd before starting it matters.
  2. Run claude from the actual monorepo root, not from a subdirectory or package.
  3. In the Claude Code session, type /allowed-paths to see what paths are currently trusted.
  4. Add the missing path: /add-dir /workspace/packages/auth/src (adjust to your actual path).
  5. Re-run the failing command.

Why this happens

The most common cause I see is launching Claude Code from a package subdirectory in a monorepo. If you cd packages/auth && claude, Claude Code sets its working directory context to packages/auth, and it won't automatically trust paths above that or in sibling packages. Then you ask it to look at shared utilities in packages/shared and it refuses.

Symlinked paths in workspaces are the second big cause. Yarn Berry and pnpm both use content-addressable stores and symlink packages into node_modules. When Claude Code follows a symlink to resolve a real path, that resolved path points into the package store, which is outside your project root. Claude Code's permission system sees a path it has never been told to trust and blocks it.

Corporate machines with SELinux or AppArmor policies are a third cause. Claude Code runs as your user but those policies can block read access to specific directories regardless of Unix permissions. This is especially common in containerized dev environments where the security policy is applied at the container level.

Permissions set during a Docker build or CI pipeline can also leave files owned by root or a service account in your working tree. When you run Claude Code as your normal user, the OS correctly denies access, and Claude Code surfaces that as a permission denied error.

Finally, on macOS with Full Disk Access not granted, Claude Code can have trouble reading certain directories that macOS protects at the TCC (Transparency, Consent, Control) level. This comes up most often with directories inside ~/Library/ or ~/Documents/ if your monorepo happens to live there.

Permanent fix

  1. Always launch Claude Code from the monorepo root:

    cd /workspace/my-monorepo
    claude
  2. Create or edit the project-level settings file to pre-approve all packages:

    // /workspace/my-monorepo/.claude/settings.json
    {
      "allowedDirectories": [
        "/workspace/my-monorepo"
      ]
    }

    The parent path covers all subdirectories recursively.

  3. Fix any files owned by root that ended up in your working tree:

    sudo chown -R $(whoami) /workspace/my-monorepo
    chmod -R u+rw /workspace/my-monorepo
  4. On macOS, grant Terminal (or your terminal app) Full Disk Access in System Settings > Privacy & Security > Full Disk Access.

  5. For pnpm workspace symlink issues, configure pnpm to not hoist packages or to use a local store inside your project:

    # .npmrc
    virtual-store-dir=.pnpm-store

    This keeps the resolved paths inside your project root.

  6. Check for SELinux denials if you're on RHEL/CentOS:

    sudo ausearch -m AVC -ts today | grep claude

    If you see denials, add a local SELinux policy module or use chcon to label the directory correctly.

  7. Verify the actual file permissions are correct:

    ls -la packages/auth/src/config.ts
    # Should show your username as owner with r-- or rw-
  8. After making permission changes, restart Claude Code. It caches path trust decisions at startup.

Prevention

Get into the habit of always running Claude Code from a fixed, stable root. I keep an alias in my shell config:

alias claude-work='cd /workspace/my-monorepo && claude'

That way I never accidentally start a session from a nested directory. It sounds trivial but it prevents 80% of the path trust issues.

For monorepos where different packages have different owners (common in large organizations where different teams maintain different packages), do a quick ls -la packages/ before starting a heavy Claude Code session. Mismatched ownership is visible immediately and takes 30 seconds to fix with chown.

Keep a project-level .claude/settings.json committed to your repo with the right allowedDirectories config. When a new developer clones the project and runs Claude Code, they get the correct setup automatically. Don't make each person configure it manually.

When the fix doesn't work

If you've fixed the filesystem permissions and the allowed paths and you're still getting denied, run Claude Code with verbose logging enabled:

CLAUDE_DEBUG=1 claude 2>&1 | tee /tmp/claude-debug.log

The debug output shows exactly which path resolution failed and why. Look for lines containing permission or access denied. That narrows down whether it's a filesystem issue, a symlink issue, or something in Claude Code's own path checker.

If the logs show the correct path being resolved but still denied, and the file permissions look correct, the issue might be with the Claude Code version you're running. Version 1.8 and earlier had a known bug where paths with spaces in directory names were incorrectly rejected. claude --version tells you what you're on. The fix landed in 1.9.

File a GitHub issue at github.com/anthropics/claude-code if none of the above resolves it. Include your OS, Claude Code version, and the specific path that's failing. The team is responsive and permission edge cases in monorepos are something they actively address.

Search