Skip to content

Commit ff11bf1

Browse files
PascalThuetclaude
andcommitted
fix(dev): report scaffold filesystem failures as a clean CLI error
The `dev integration scaffold` command only caught FileExistsError/ValueError, so an OSError raised during mkdir()/write_text() (permission denied, read-only checkout, a path component that is a file, ...) bubbled up as a traceback instead of a clean error + exit code. Broaden the handler to OSError (which also covers FileExistsError) and add coverage for the filesystem-error path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent dfde970 commit ff11bf1

2 files changed

Lines changed: 27 additions & 1 deletion

File tree

src/specify_cli/__init__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,11 @@ def dev_integration_scaffold(
605605
project_root = Path.cwd()
606606
try:
607607
result = scaffold_integration(project_root, key, integration_type)
608-
except (FileExistsError, ValueError) as exc:
608+
except (OSError, ValueError) as exc:
609+
# OSError covers filesystem failures during mkdir()/write_text()
610+
# (permission denied, read-only checkout, a path component that is a
611+
# file, ...) as well as FileExistsError; surface them as a clean CLI
612+
# error instead of a traceback.
609613
console.print(f"[red]Error:[/red] {exc}")
610614
raise typer.Exit(1)
611615

tests/integrations/test_integration_scaffold.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,28 @@ def test_dev_integration_scaffold_rejects_unknown_type_before_scaffolding(tmp_pa
102102
assert not (root / "src" / "specify_cli" / "integrations" / "my_agent").exists()
103103

104104

105+
def test_dev_integration_scaffold_reports_filesystem_errors_cleanly(tmp_path, monkeypatch):
106+
root = _repo_root(tmp_path)
107+
monkeypatch.chdir(root)
108+
109+
import specify_cli.integration_scaffold as scaffold_module
110+
111+
def boom(*args, **kwargs):
112+
raise PermissionError("Permission denied: read-only checkout")
113+
114+
monkeypatch.setattr(scaffold_module, "scaffold_integration", boom)
115+
116+
result = runner.invoke(app, [
117+
"dev", "integration", "scaffold", "my-agent",
118+
"--type", "markdown",
119+
], catch_exceptions=False)
120+
121+
output = strip_ansi(result.output)
122+
assert result.exit_code == 1
123+
assert "Error:" in output
124+
assert "Permission denied" in output
125+
126+
105127
def test_scaffold_refuses_invalid_key(tmp_path):
106128
root = _repo_root(tmp_path)
107129

0 commit comments

Comments
 (0)