Lesson 24: Troubleshoot — Permission Errors & Config Conflicts
Day 24 of 50 · ~10 min reading · Phase 3: Customization
Introduction
You've set up your project with CLAUDE.md, permissions, commands, rules, and skills. Everything's working beautifully... until something goes wrong.
Claude suddenly can't do something you expected. Or it's ignoring your rules. Or you get an error about permissions.
This lesson teaches you how to diagnose and fix three common configuration problems.
Scenario 1: Permission Mode Blocks a Needed Action
What Happened
You're in the middle of a complex refactoring. Claude says:
"I'd like to run
npm testto verify my changes, but this action requires your approval. Approve?"
You've set permissions to "ask every time," and now Claude is asking about something you do 50 times a day. It's slowing you down.
What It Looks Like
[In Claude Code conversation]
Claude: I've refactored the function. Let me run tests to verify.
> Approve running: bash command "npm test"?
User: [clicks approve, again]
Claude: Tests passed. Now let me refactor the next function.
> Approve running: bash command "npm test"?
User: [frustrated, clicks approve again]
Or the opposite problem:
[In Claude Code conversation]
Claude: I'll push these changes to main.
[Push happens without asking]
User: No! I didn't approve that!
Diagnose
The problem is your permission settings don't match your workflow.
Check .claude/settings.json:
cat .claude/settings.json
If you see:
{
"permissions": {
"mode": "ask_every_time"
}
}
And you keep approving the same actions, your permissions are too strict.
If you see a permissive mode but Claude did something risky without asking, your permissions are too loose.
Fix
Tighten or loosen permissions strategically.
If certain actions (like npm test) are safe and you do them constantly, allowlist them:
{
"permissions": {
"mode": "plan",
"bypassTools": {
"allowed": ["bash:npm test", "bash:npm run lint", "bash:git status"]
}
}
}
If you're nervous about a specific dangerous action, blocklist it:
{
"permissions": {
"mode": "plan",
"bypassTools": {
"blocked": ["bash:git push origin main", "bash:rm -rf"]
}
}
}
Then test it: Run a task and verify Claude behaves as expected.
Lesson Learned
Permissions are a tradeoff between safety and speed. Find the sweet spot for your workflow. If you're waiting for approvals constantly, loosen permissions. If you're nervous Claude will break something, tighten them. You can always adjust later.
The goal isn't to be maximally safe or maximally fast — it's to be safe enough while staying productive.
Scenario 2: CLAUDE.md Is Too Long and Claude Ignores Parts
What Happened
You spent time documenting everything in CLAUDE.md. You included:
- Project history
- Detailed architecture diagrams
- Every edge case and exception
- Philosophy on code quality
- Team conventions
- Build system deep dive
It's comprehensive and helpful. But now Claude is ignoring some of it. Claude asks about things you documented or follows patterns differently than you specified.
What It Looks Like
Your CLAUDE.md says:
"Always use async/await, never use .then()"
Claude creates a new function using .then() anyway:
```typescript
db.query().then(result => { ... })
You ask: "Why didn't you use async/await?" Claude: "I don't have that pattern in my context."
Or:
Your CLAUDE.md says: "Tests go in /tests directory"
Claude creates tests in tests instead. You ask why. Claude: "I didn't see that documented."
### Diagnose
**The problem is your CLAUDE.md is too long.**
Check the file:
```bash
wc -l CLAUDE.md
If it's over 200-300 lines, context window pressure is eating into Claude's ability to apply your conventions. Claude has limited space, and a massive CLAUDE.md takes up space that could be used for the actual task.
Also check: Is the information you need buried deep?
If the convention Claude missed is on line 180 in a 400-line file, Claude might not have seen it before running out of context.
Fix
Cut CLAUDE.md down to essentials.
Keep:
- Quick project overview (2-3 lines)
- How to test (2-3 lines)
- How to build (2-3 lines)
- Critical conventions (5-10 lines)
- Key patterns (5-10 lines)
Move to rules or separate docs:
- Architecture deep dives → create rules for
/src,/api, etc. - Edge cases and exceptions →
.claude/memory/ - Philosophy and history → separate README.md for humans
- Detailed patterns →
.claude/skills/
Example: before (too long)
# Our Project
## History
Founded in 2020, blah blah blah...
[10 lines]
## Philosophy
We believe in clean code and strong types...
[15 lines]
## Style Guide (Comprehensive)
[50 lines covering every possible scenario]
## Testing Strategy (Detailed)
[40 lines with rationale and examples]
## Deployment Process
[30 lines with links and references]
Example: after (lean)
# Project: Task Manager
## Tech
Node.js + React + TypeScript
## Test
`npm test` — tests in `/tests`, Jest framework
## Build
`npm run build` → `/dist`
## Style
- async/await, no .then()
- camelCase functions, PascalCase components
- Absolute imports with @/alias
## Key rules
- TypeScript required (no any)
- Every feature needs tests
- Validate all inputs
Then create .claude/rules/src.rules.md for detailed conventions in that directory.
Lesson Learned
Brevity is a feature. A tight CLAUDE.md costs less context and forces you to identify what actually matters. Details belong in rules, memory, or regular documentation. Claude reads CLAUDE.md before the conversation starts — make it count, not make it comprehensive.
Scenario 3: Conflicting Rules Cause Unexpected Behavior
What Happened
You have rules in multiple places:
- CLAUDE.md says: "Use async/await"
.claude/rules/src.rules.mdsays: "Use async/await".claude/memory/patterns.mdmentions: "Avoid async/await for simple operations"
Now Claude is confused about what to do. Different parts of your configuration are giving different signals.
Or perhaps:
- CLAUDE.md says: "Tests go in
/tests" .claude/rules/src.rules.mdsays: "Tests go in__tests__alongside source"
Now when Claude creates a test in /src, is it following global rules or local rules?
What It Looks Like
In a conversation:
Claude: I need to get user data. Should I use async/await?
User: Yes, like I said in CLAUDE.md
Claude: But memory says to avoid it for simple cases...
[Claude writes something inconsistent]
Or Claude creates tests in one place in some parts of the code and another place in other parts.
Diagnose
The problem is your configuration has contradictions.
Check for conflicts:
-
CLAUDE.md vs. rules: If CLAUDE.md and
.claude/rules/say different things, which wins? (Answer: rules are path-specific and override global, but it's confusing.) -
Rules vs. memory: If a rule says "always use TypeScript" but memory says "JavaScript is fine for scripts," Claude might be uncertain.
-
Multiple memory files: If you have multiple
.claude/memory/files saying different things, Claude has to reconcile them. -
Old vs. new: If you have outdated documentation, Claude might follow old patterns.
Fix
Enforce one source of truth per category.
Global conventions → CLAUDE.md only
- Tech stack
- How to test
- How to build
- Key style rules (2-3 most important)
Local conventions → Rules only
- Directory-specific patterns
- Different style for different areas (API might be different from frontend)
Lessons learned → Memory only
- "We tried this pattern and it didn't work"
- "This error means X"
- Debugging hints
Specific tasks → Skills only
- "To add a component, do this"
- "To deploy, follow these steps"
Then delete or consolidate:
# If CLAUDE.md and rules say the same thing, delete from rules
# If memory contradicts current practice, update it or delete it
# If a skill contradicts rules, delete the contradiction from the skill
Example: before (conflicting)
CLAUDE.md: "Tests in /tests with Jest"
Rules: "Tests alongside source in __tests__"
Memory: "Jest for unit tests, Mocha for integration"
Skill: "Create tests in __tests__"
Example: after (coherent)
CLAUDE.md: "Tests use Jest in /tests directory"
Rules: (empty — no need to repeat global)
Memory: "We tried Mocha and switched to Jest in 2024"
Skill: "Create test in /tests following Jest patterns"
Lesson Learned
Your configuration should be consistent. Don't make Claude guess which rule applies. One level should be primary:
- CLAUDE.md for global
- Rules for local overrides
- Memory for lessons, not current policy
- Skills for tasks, not conventions
If you notice contradiction, clean it up. Claude will work better, and so will you (you'll understand your own project better).
Prevention Checklist
Before deploying a configuration, ask:
- Is CLAUDE.md under 200 lines?
- Does CLAUDE.md have any contradictions with rules?
- Do rules contradict each other or CLAUDE.md?
- Is memory documenting lessons, not current policy?
- Are skills teaching tasks, not conventions?
- Can I explain my permission settings in one sentence?
- Have I tested the configuration in a real task?
Key Takeaway
Configuration problems usually come from three things: permissions don't match your workflow, documentation is too large or scattered, or conflicting information confuses Claude. The fixes are simple: align permissions, tighten documentation, and establish one source of truth for each category. When in doubt, less is more — lean documentation beats comprehensive documentation.
What's Next?
You've now mastered Phase 3: customization. You know how to teach Claude about your project, set boundaries, create workflows, and avoid configuration pitfalls.
Phase 4 introduces a new dimension: What happens when Claude reaches outside your project? How do you let Claude connect to APIs, databases, external tools, and services?
The answer is MCP — the Model Context Protocol. It's how Claude's context extends beyond your filesystem.