Skip to content

Bug: Temp Directory Leak When Clone Fails in agentic_change.py #18

@Serhan-Asad

Description

@Serhan-Asad

Summary

When pdd fix fails to clone a repository (or crashes mid-execution), the temporary directory created by _setup_repository() is not cleaned up, causing a disk space leak.

Location

File: pdd/pdd/agentic_change.py
Function: _setup_repository() (lines 111-136)
Caller: run_agentic_change() (lines 222-245)

Problem

The code creates a temporary directory using tempfile.mkdtemp() but doesn't clean it up when:

  1. Clone fails (network error, auth error, etc.)
  2. Orchestrator crashes mid-execution
  3. Any exception occurs before cleanup

Current Code Flow

```python

Line 112: Create temp directory

temp_dir = Path(tempfile.mkdtemp(prefix=f"pdd_{repo}_"))

Lines 123-134: Try to clone

try:
result = subprocess.run(...)
if result.returncode != 0:
raise RuntimeError(...) # ❌ Exits without cleanup!
except Exception as e:
raise RuntimeError(...) # ❌ Exits without cleanup!

return temp_dir
```

Missing Cleanup

Unlike agentic_test.py which has cleanup in a finally block (lines 253-262), agentic_change.py has no cleanup code.

Impact

Disk Space Leak

  • Empty folder leak: If clone fails → empty directory left behind (~0 bytes)
  • Full repo leak: If orchestrator crashes → entire cloned repository left behind (could be MBs)
  • Partial work leak: If crashes mid-execution → repo + partial changes left behind (could be MBs)

Real-World Scenarios

  1. CI/CD with network issues: Issue fetched via API, then network drops during clone
  2. Rate limiting: API works but git operations get rate-limited
  3. Private repos: Issue is public but repo requires auth
  4. Disk full: Clone starts but fails mid-way
  5. Orchestrator crashes: Any exception during execution leaves temp folder

Evidence

Test Results

```bash

Before test

Temp folders: 0

Run: pdd fix facebook/react#1

(with test line forcing failure)

After test

Temp folders: 1
Leaked folder: /var/folders/.../T/pdd_react_04d40tvw
Status: Empty directory (clone failed)
```

Code Comparison

agentic_test.py (HAS cleanup):
```python
try:
return run_agentic_test_orchestrator(...)
except Exception as e:
return False, ...
finally:
# Cleanup if we created a temp directory
if repo_path != current_cwd and repo_path.exists():
shutil.rmtree(repo_path) # ✅ CLEANS UP!
```

agentic_change.py (MISSING cleanup):
```python
try:
work_dir = _setup_repository(...)
except RuntimeError as e:
return False, str(e), ... # ❌ Exits without cleanup!

NO FINALLY BLOCK!

return run_agentic_change_orchestrator(...)
```

Recommended Fix

Add cleanup similar to agentic_test.py:

```python

6. Setup Repository (Clone or Use Current)

current_cwd = Path.cwd()
work_dir = None
try:
work_dir = _setup_repository(owner, repo, quiet)
except RuntimeError as e:
return False, str(e), 0.0, "", []

7. Run Orchestrator

try:
if not quiet:
console.print(f"[bold green]Starting Agentic Change Orchestrator...[/bold green]")

return run_agentic_change_orchestrator(
    issue_url=issue_url,
    issue_content=issue_content,
    repo_owner=owner,
    repo_name=repo,
    issue_number=issue_number,
    issue_author=author,
    issue_title=title,
    cwd=work_dir,
    verbose=verbose,
    quiet=quiet,
    timeout_adder=timeout_adder,
    use_github_state=use_github_state
)

finally:
# Cleanup if we created a temp directory
if work_dir and work_dir != current_cwd and work_dir.exists():
if not quiet:
console.print(f"[dim]Cleaning up temporary repository at {work_dir}...[/dim]")
try:
shutil.rmtree(work_dir)
except Exception as e:
if verbose:
console.print(f"[yellow]Warning: Failed to cleanup temp dir: {e}[/yellow]")
```

Severity

Medium-High

  • Blocks disk space over time
  • Worse for CI/CD environments (many runs = many leaks)
  • Can accumulate hundreds of MBs if orchestrator crashes after cloning large repos

Related Files

  • pdd/pdd/agentic_test.py - Has proper cleanup (reference implementation)
  • pdd/pdd/agentic_change.py - Missing cleanup (bug location)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions