Skill: Fix Directory Not Created Before Write
Overview
| Field | Value |
|---|---|
| Date | 2026-01-18 |
| Category | Evaluation / Debugging |
| Objective | Fix FileNotFoundError when writing to directory that was assigned but not created |
| Outcome | ✓ Success - Single line fix resolved intermittent parallel execution bug |
| Session ID | skill/evaluation/fix-judge-file-access |
When to Use This Skill
Use this debugging pattern when encountering:
- •Intermittent FileNotFoundError in parallel execution contexts
- •Directory path assignment without mkdir() before file write operations
- •Race conditions where subdirectories sometimes create parent dirs, sometimes don't
- •Error pattern:
FileNotFoundError: 'path/to/parent_dir/file.json'
Trigger Conditions
- •Error only occurs when child operations are skipped (checkpoint, early exit)
- •Works when child operations run (they implicitly create parent directory)
- •Parallel execution context where timing affects directory creation order
Problem Pattern
Vulnerable Code Pattern
python
# VULNERABLE: Directory assigned but not created parent_dir = base_path / "tier_name" # ... other operations ... # FAILS: Tries to write to parent_dir before it exists write_file(parent_dir / "result.json", data)
Root Cause
- •Directory assignment != directory creation in Python pathlib
- •Implicit creation by subdirectories masks the bug temporarily
- •Parallel execution + checkpoints expose the race condition
Verified Workflow
Step 1: Identify the Assignment Location
Search for where the problematic directory path is assigned:
bash
grep -n "problematic_dir = " scylla/path/to/file.py
Step 2: Verify No mkdir() Call
Check if mkdir() is called immediately after assignment:
python
# BEFORE (bug) tier_dir = self.experiment_dir / tier_id.value # No mkdir() here! # ... code continues ... # FAILS HERE save_selection(selection, str(tier_dir / "best_subtest.json"))
Step 3: Add mkdir() Immediately After Assignment
python
# AFTER (fixed) tier_dir = self.experiment_dir / tier_id.value tier_dir.mkdir(parents=True, exist_ok=True) # ← Add this line # Now this works reliably save_selection(selection, str(tier_dir / "best_subtest.json"))
Step 4: Verify the Fix
bash
# Run the command that previously failed pixi run python scripts/run_experiment.py --all-tiers --fresh # Verify directory is created before file operations ls -la results/experiment/tier_name/ # Should exist immediately
Failed Attempts
None - The root cause was clear from the stack trace and the first solution worked.
Why This Worked First Try
- •Clear error message pointed to exact file path
- •Stack trace showed
save_selection()callingopen()on non-existent directory - •Code inspection revealed assignment without creation
- •Pattern recognition from pathlib behavior: assignment ≠ creation
Key Insights
Critical Understanding
- •Python pathlib
Pathassignment does NOT create directories - •Always call
.mkdir(parents=True, exist_ok=True)after assignment - •Parallel execution + checkpoint resume exposes these bugs
- •Child operations can mask parent directory bugs by implicitly creating parents
Best Practice Pattern
python
# ALWAYS follow this pattern for directories that will contain files: directory_path = parent_path / "subdir" directory_path.mkdir(parents=True, exist_ok=True) # Create immediately # Now safe to write files (directory_path / "file.json").write_text(data)
Parameters That Matter
- •
parents=True- Creates parent directories if needed - •
exist_ok=True- Doesn't error if directory already exists (idempotent)
Results & Verification
Fix Location
File: scylla/e2e/runner.py:625
Change:
diff
# Prepare results directory tier_dir = self.experiment_dir / tier_id.value + tier_dir.mkdir(parents=True, exist_ok=True)
Verification Command
bash
pixi run python scripts/run_e2e_experiment.py \ --tiers-dir tests/fixtures/tests/test-002 \ --tiers T0 T1 T2 T3 T4 T5 T6 \ --runs 1 --max-subtests 2 -v --fresh
Success Criteria
- •✓ No FileNotFoundError in any tier
- •✓ All tier directories created at start of tier execution
- •✓ T3 directory existed before save_selection() called
- •✓ Parallel execution completed without race conditions
Commit
code
fix(e2e): create tier directory before writing best_subtest.json Fix FileNotFoundError when save_selection() tries to write to tier_dir/best_subtest.json before the directory exists. Solution: Add tier_dir.mkdir(parents=True, exist_ok=True) immediately after tier_dir assignment to ensure the directory exists before any write operations.
Reusability
This pattern applies to any code where:
- •A directory path is constructed from parent + child
- •Files are written directly to that directory (not just subdirectories)
- •There's a gap between path assignment and file write
- •The code runs in parallel or with conditional execution paths
Common Locations
- •Result directory setup in parallel executors
- •Temporary workspace creation in multi-threaded code
- •Checkpoint/resume systems where directory creation might be skipped
- •Any path construction followed by
open(path, 'w')or.write_text()
Related Issues
- •Race conditions in parallel execution
- •Checkpoint resume skipping initialization steps
- •Directory creation assumptions in filesystem operations
- •Pathlib vs os.path behavior differences