Skip to content

fix(extensions): show catalog entries missing name, version or description - #5308

Open
kartsan03 wants to merge 1 commit into
github:mainfrom
kartsan03:fix/extension-display-incomplete-catalog-entry
Open

kartsan03 wants to merge 1 commit into
github:mainfrom
kartsan03:fix/extension-display-incomplete-catalog-entry

Conversation

@kartsan03

Copy link
Copy Markdown
Contributor

Description

specify extension search and specify extension info indexed a catalog entry's name, version and description directly, so an entry missing one of them made both commands exit 1 with a KeyError (#5307). Search stopped at that entry, so the extensions after it were never listed. Catalog entries are kept without per-field validation on purpose (_get_merged_extensions: "one malformed entry shouldn't poison an otherwise valid catalog"), and #5108 made extension update skip a versionless entry for the same reason.

The two display paths now read those fields with .get(), using the fallbacks the extensions code already has: unknown for a missing version (as in extension add and info for an installed extension), the extension ID for a missing name, and an empty description (as search() already treats it when filtering). Values are still escaped for Rich as before.

Repro with the real CLI: a project whose cached catalog holds one complete entry (healthy) and one entry (example) missing a single field. Steps are in #5307.

example is missing Command main (c438494) This PR
version extension search exit 1, KeyError: 'version' exit 0, Example (vunknown) and Healthy (v2.0.0)
version extension info example exit 1, KeyError: 'version' exit 0, Example (vunknown)
name extension search exit 1, KeyError: 'name' exit 0, example (v1.0.0) and Healthy (v2.0.0)
name extension info example exit 1, KeyError: 'name' exit 0, example (v1.0.0)
description extension search exit 1, KeyError: 'description' exit 0, both entries
description extension info example exit 1, KeyError: 'description' exit 0

Fixes #5307

Testing

  • Tested locally with uv run specify --help
  • Ran existing tests with uv sync && uv run pytest
  • Tested with a sample project (if applicable)

A new fixture in tests/specify_cli/extensions/conftest.py, incomplete_catalog_entry, writes a fresh catalog cache with the incomplete entry and a complete sibling, and fails the test if the catalog is fetched from the network. It runs four cases: no version, no name, no description, and a version holding Rich markup.

  • TestExtensionSearchCLI.test_search_shows_incomplete_catalog_entry: unfiltered search lists both entries with the expected headers, and search Healthy still filters the incomplete one out.
  • TestExtensionInfoCLI.test_info_shows_incomplete_catalog_entry: info example and info healthy both exit 0 with the expected headers.

With command_search.py and command_info.py reverted to main, the three missing-field cases of each test fail (6 of 8). The markup cases pass on main too, since escaping already worked.

Full suite on Linux, Python 3.13: 13961 passed, 449 skipped, 1 failed (pytest -n 2, 7 min). The failure, test_version_execution.py::TestWindowsUvToolEnvironment::test_non_windows_uv_tool_dry_run_still_previews_installer, fails the same way on main here: Rich wraps the dry-run output, and my checkout's venv path is long enough to be split mid-path. Ruff 0.15.0 (ruff check src tests) passes. I haven't run it on Windows.

AI Disclosure

  • I did not use AI assistance for this contribution
  • I did use AI assistance (fill in the disclosure below)

AI disclosure: Codex CLI (model: gpt-6.1-sol, reasoning effort xhigh, autonomous, offline sandbox) found the missing-version crash and wrote the first fix and tests. Claude Code (model: claude-opus-5-5, autonomous) extended the fix and tests to name and description, reran the repro with the real CLI on main and the branch, ran the full suite and lint, and drafted this description. The commit carries Assisted-by: trailers for both.

…ption

`extension search` and `extension info` indexed a catalog entry's name,
version and description directly, so an entry without one of them made
both commands exit with a KeyError, and search never listed the entries
after it. Catalog entries are not validated field by field on purpose,
and `extension update` already skips a versionless entry (github#5108).

Read the three fields with .get(): `unknown` for a missing version (as
`extension add` and installed-extension info show it), the extension ID
for a missing name, and an empty description.

Assisted-by: Codex CLI (model: gpt-6.1-sol, autonomous)
Assisted-by: Claude Code (model: claude-opus-5-5, autonomous)
@kartsan03
kartsan03 requested a review from mnriem as a code owner November 7, 2026 22:25
Copilot AI auto review requested due to automatic review settings November 7, 2026 22:25

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.

🟢 Approval recommended

The changes address missing catalog metadata with safe fallbacks while preserving search behavior and Rich escaping, alongside regression coverage for incomplete entries.

No open issues 🎉

What changed in this PR

Updates specify extension search and specify extension info to handle catalog entries missing name, version, or description without raising KeyError.

Changes:

  • Added fallbacks for missing metadata: extension ID for names, unknown for versions, and an empty description.
  • Preserved Rich markup escaping and search filtering behavior.
  • Added cached catalog fixtures and parameterized CLI regression tests.
File Description
tests/​specify_cli/​extensions/​test_command_search.py Verifies incomplete entries display correctly and filtering continues to work.
tests/​specify_cli/​extensions/​test_command_info.py Verifies incomplete and complete catalog entries display successfully.
tests/​specify_cli/​extensions/​conftest.py Adds cached catalog fixtures covering missing fields and Rich markup.
src/​specify_cli/​extensions/​command_search.py Safely renders incomplete catalog metadata during search.
src/​specify_cli/​extensions/​command_info.py Safely renders incomplete catalog metadata in extension details.

Review effort: Lite (auto)

This branch has not been deployed

No deployments
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.

[Bug]: extension search and extension info crash with KeyError on a catalog entry without name, version or description

2 participants