Skip to content

fix(extensions): start fresh on a non-UTF-8 extension registry - #3954

Open
marcelsafin wants to merge 2 commits into
github:mainfrom
marcelsafin:fix/ext-registry-decode
Open

fix(extensions): start fresh on a non-UTF-8 extension registry#3954
marcelsafin wants to merge 2 commits into
github:mainfrom
marcelsafin:fix/ext-registry-decode

Conversation

@marcelsafin

@marcelsafin marcelsafin commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Description

ExtensionRegistry._load() catches json.JSONDecodeError and FileNotFoundError to start fresh on a corrupted or missing .specify/extensions/.registry, but a registry file containing invalid UTF-8 bytes raises UnicodeDecodeError before JSON parsing begins — crashing every extension command with a raw traceback.

Repro on main:

printf '\xff\xfe' > .specify/extensions/.registry
specify extension list
# UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0

Fix: catch UnicodeDecodeError in the same clause — undecodable bytes are the same corruption class as unparseable JSON. OSError deliberately stays uncaught: the data may be intact on disk, and starting fresh would let a later _save() wipe it (same fail-closed reasoning as the workflow catalog cache loader).

The existing test test_non_utf8_registry_does_not_crash documents that _sibling_extension_ids works around this gap; this PR fixes the source so the workaround is consistent with _load() itself.

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_load_starts_fresh_for_non_utf8_registry (fails on main, 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.

ExtensionRegistry._load() catches json.JSONDecodeError and
FileNotFoundError to start fresh on a corrupted or missing registry, but
a registry file with invalid UTF-8 bytes raised UnicodeDecodeError
before JSON parsing began, crashing every extension command.

Catch UnicodeDecodeError in the same clause: undecodable bytes are the
same corruption class as unparseable JSON. OSError stays uncaught on
purpose — the data may be intact on disk, and starting fresh would let a
later _save() wipe it (same fail-closed reasoning as the workflow
catalog cache loader).

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:54
Copilot AI review requested due to automatic review settings August 3, 2026 19:54

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

Handles non-UTF-8 extension registries as corrupted data instead of crashing extension commands.

Changes:

  • Catches UnicodeDecodeError during registry loading.
  • Adds regression coverage for invalid UTF-8 bytes.

Reviewed changes

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

File Description
src/specify_cli/extensions/__init__.py Handles undecodable registry content.
tests/test_extensions.py Tests fresh-state fallback for invalid UTF-8.

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

Comment thread src/specify_cli/extensions/__init__.py
Comment thread tests/test_extensions.py
…eError

Review follow-up: _sibling_extension_ids and
test_non_utf8_registry_does_not_crash documented the pre-fix _load()
contract; reword both as defense-in-depth so the rationale stays true.

Assisted-by: GitHub Copilot (model: claude-fable-5, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 3, 2026 20:13

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

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

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