Skip to content

fix(presets): start fresh on a non-UTF-8 preset registry - #3955

Open
marcelsafin wants to merge 1 commit into
github:mainfrom
marcelsafin:fix/preset-registry-decode
Open

fix(presets): start fresh on a non-UTF-8 preset registry#3955
marcelsafin wants to merge 1 commit into
github:mainfrom
marcelsafin:fix/preset-registry-decode

Conversation

@marcelsafin

@marcelsafin marcelsafin commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Description

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

Repro on main:

printf '\xff\xfe' > .specify/presets/.registry
specify preset 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).

Exact twin of the extension-registry gap (#3954), kept as a separate PR per bug for isolated review/revert.

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.

PresetRegistry._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 preset 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>
Copilot AI review requested due to automatic review settings August 3, 2026 19:54
@marcelsafin
marcelsafin requested a review from mnriem as a code owner 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 preset registries as corrupted data instead of crashing.

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 1 comment.

File Description
src/specify_cli/presets/__init__.py Recovers from undecodable registry files.
tests/test_presets.py Tests non-UTF-8 registry recovery.

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

Comment thread tests/test_presets.py
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