Skip to content

fix(extensions): reject reinstall when a kept config cannot be read - #3960

Open
marcelsafin wants to merge 1 commit into
github:mainfrom
marcelsafin:fix/keep-config-rescue-read
Open

fix(extensions): reject reinstall when a kept config cannot be read#3960
marcelsafin wants to merge 1 commit into
github:mainfrom
marcelsafin:fix/keep-config-rescue-read

Conversation

@marcelsafin

Copy link
Copy Markdown
Contributor

Description

The keep-config rescue branch of install_from_directory() reads each preserved config with bare read_bytes()/stat() calls, so a kept config that cannot be read (permission or I/O error) crashes the reinstall with a raw OSError. The sibling symlink guard four lines above already rejects with a ValidationError and resolution guidance for exactly the same reason: bytes that cannot be safely rescued must never reach the rmtree below.

Fix: wrap the read and raise ValidationError with guidance (fix its permissions or remove it, then reinstall) while dest_dir is still untouched, so the preserved bytes are never rescued half-read or lost.

Testing

  • Tested locally with uv run specify --help
  • Ran existing tests with uv sync && uv run pytest (6,310 passed, 176 skipped)
  • New regression test test_reinstall_with_unreadable_kept_config_aborts_with_guidance (fails on main with raw PermissionError, passes with fix)
  • ruff check src tests clean

AI Disclosure

  • I did not use AI assistance for this contribution
  • I did use AI assistance (describe below)

Implemented autonomously by GitHub Copilot CLI (model: Claude Fable 5) under human direction; TDD (failing test first), full suite and lint verified locally. Commit includes Assisted-by/Co-authored-by trailers.

The keep-config rescue branch of install_from_directory() reads each
preserved config with bare read_bytes()/stat() calls, so a kept config
that cannot be read (permission or I/O error) crashed the reinstall
with a raw OSError. The sibling symlink guard four lines above already
rejects with a ValidationError and resolution guidance for the same
reason: bytes that cannot be safely rescued must not reach the rmtree
below.

Wrap the read and raise ValidationError with guidance, while dest_dir
is still untouched so the preserved bytes are never lost.

Assisted-by: GitHub Copilot (model: claude-fable-5, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@marcelsafin
marcelsafin requested a review from mnriem as a code owner August 3, 2026 19:56
Copilot AI review requested due to automatic review settings August 3, 2026 19:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds safe error handling when reinstalling an extension whose preserved configuration cannot be read.

Changes:

  • Converts config read/stat failures into actionable ValidationErrors before deletion.
  • Adds regression coverage confirming the config remains untouched.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/specify_cli/extensions/__init__.py Handles preserved-config read failures safely.
tests/test_extensions.py Tests unreadable preserved-config behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants