[BUG] ENAMETOOLONG when saving conversation history with deeply nested working directories

Resolved 💬 7 comments Opened Nov 2, 2025 by Elijas Closed Jan 21, 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?

When working in a deeply nested directory structure, Claude Code crashes with an ENAMETOOLONG error during conversation. The error occurs when Claude Code attempts to create the project directory for storing conversation transcripts.

The error shows:

Error: ENAMETOOLONG: name too long, mkdir '/Users/user/.claude/projects/-Users-user-Development-project-alpha-v1-feature-backend-api-v2-module-auth-service-tests-unit-integration-e2e-fixtures-mocks-helpers-utils-config'
    at Module.mkdirSync (node:fs:1325:26)
    at Object.mkdirSync
(file:///opt/homebrew/lib/node_modules/@anthropic-ai/claude-code/cli.js:9:1190)
    at _c2.appendEntry
(file:///opt/homebrew/lib/node_modules/@anthropic-ai/claude-code/cli.js:3593:2955)
    at _c2.insertMessageChain
(file:///opt/homebrew/lib/node_modules/@anthropic-ai/claude-code/cli.js:3593:2255)

The constructed path exceeds macOS filesystem limits (typically 255 characters for a path component).

What Should Happen?

Claude Code should handle long working directory paths gracefully by:

  1. Shortening the project directory name to stay within filesystem limits
  2. Keeping the name human-readable (not just a hash)
  3. Maintaining uniqueness via embedded hash

Similar to how git creates .git directories regardless of the repository path length.

Error Messages/Logs

Error: ENAMETOOLONG: name too long, mkdir '/Users/user/.claude/projects/-Users-user-Development-project-alpha-v1-feature-backend-api-v2-module-auth-service-tests-unit-integration-e2e-fixtures-mocks-helpers-utils-config'
    at Module.mkdirSync (node:fs:1325:26)
    at Object.mkdirSync
(file:///opt/homebrew/lib/node_modules/@anthropic-ai/claude-code/cli.js:9:1190)
    at _c2.appendEntry
(file:///opt/homebrew/lib/node_modules/@anthropic-ai/claude-code/cli.js:3593:2955)
    at _c2.insertMessageChain
(file:///opt/homebrew/lib/node_modules/@anthropic-ai/claude-code/cli.js:3593:2255)
    at process.processTicksAndRejections (node:internal/process/task_queues:103:5)

Steps to Reproduce

  1. Create a deeply nested directory structure:

``bash
mkdir -p ~/Development/project-alpha-v1/feature-backend-api-v2/module-auth-service/tests-unit/integration-e2e/fixtures-mocks/helpers-utils/config-settings/docs-examples
``

  1. Navigate into the deeply nested directory:

``bash
cd ~/Development/project-alpha-v1/feature-backend-api-v2/module-auth-service/tests-unit/integration-e2e/fixtures-mocks/helpers-utils/config-settings/docs-examples
``

  1. Start Claude Code and have a conversation:

``bash
claude
``

  1. After any assistant response with tool usage, the error occurs as Claude tries to save the conversation transcript.

Note: The bug triggers when the constructed path ~/.claude/projects/{encoded-working-directory-path} exceeds filesystem limits. On macOS, this is typically 255 characters for a single path component.

Claude Model

Not sure / Multiple models

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.0.31 (Claude Code)

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

Still reproducible in 2.0.76 — see #19742 for updated reproduction steps.

This issue is related to but distinct from:

  • #7940 - Similar ENAMETOOLONG but during directory traversal (readdir), not conversation storage (mkdirSync)
  • #3411 - ENAMETOOLONG for CLI arguments, not file paths (already fixed)

Root Cause:
Claude Code derives the project directory name from the absolute working directory path by replacing / with -. With deeply nested directories, this can exceed the 255-character limit on macOS.

Suggested Fix:
Use smart truncation with embedded hash — similar to how "a16z" represents "Andreessen Horowitz". Keep the beginning and end readable, replace the overflow middle with a short hash:

const crypto = require('crypto');
const MAX_LEN = 250; // Leave room for filesystem overhead
const HASH_LEN = 8;

function safeProjectName(workingDirectory) {
  const name = workingDirectory.replace(/\//g, '-').replace(/^-/, '');
  
  if (name.length <= MAX_LEN) {
    return name;
  }
  
  // Hash the full path for uniqueness
  const hash = crypto.createHash('sha256')
    .update(workingDirectory)
    .digest('hex')
    .substring(0, HASH_LEN);
  
  // Keep prefix and suffix readable, embed hash in middle
  const available = MAX_LEN - HASH_LEN - 4; // 4 for "--" delimiters
  const prefixLen = Math.floor(available * 0.6);
  const suffixLen = available - prefixLen;
  
  const prefix = name.substring(0, prefixLen);
  const suffix = name.substring(name.length - suffixLen);
  
  return `${prefix}--${hash}--${suffix}`;
}

Example:

Before (too long, CRASHES):
-Users-user-Development-project-alpha-enterprise-v1-feature-backend-api-gateway-v2-module-auth-...-resources-assets-templates

After (250 chars, recognizable):
-Users-user-Development-project-alpha-enterprise-v1-feature-backend--a1b2c3d4--options-params-documentation-examples-samples-resources-assets-templates

Benefits:

  • Still human-readable — you can identify the project from ls ~/.claude/projects/
  • Guaranteed unique via hash
  • Never exceeds filesystem limits
  • No separate mapping file needed

View original on GitHub ↗

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