[BUG] ENAMETOOLONG when saving conversation history with deeply nested working directories
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:
- Shortening the project directory name to stay within filesystem limits
- Keeping the name human-readable (not just a hash)
- 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
- 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
- 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
- Start Claude Code and have a conversation:
``bash``
claude
- 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
This issue has 7 comments on GitHub. Read the full discussion on GitHub ↗