Skip to content

fix(extensions): tolerate non-string catalog name in display-name lookup#3747

Open
Noor-ul-ain001 wants to merge 1 commit into
github:mainfrom
Noor-ul-ain001:fix/ext-resolve-nonstring-name
Open

fix(extensions): tolerate non-string catalog name in display-name lookup#3747
Noor-ul-ain001 wants to merge 1 commit into
github:mainfrom
Noor-ul-ain001:fix/ext-resolve-nonstring-name

Conversation

@Noor-ul-ain001

Copy link
Copy Markdown
Contributor

@

Summary

_resolve_catalog_extension() (used by extension info <name> and extension add <name>) resolves an argument to a catalog entry by display name:

search_results = catalog.search(query=argument)
name_matches = [ext for ext in search_results if ext["name"].lower() == argument.lower()]

Extension catalog JSON is user-editable, so catalog.search() can return an entry whose name is a non-string. A hand-authored name: 123 crashes the filter:

AttributeError: int object has no attribute lower

which takes down extension info <name> / extension add <name> with a raw traceback. A missing name key would similarly raise KeyError.

Notably, the ambiguous-match display block a few lines below already str()-coerces the name (_escape_markup(str(ext.get("name", "")))) — so the code already acknowledges name may be non-string/absent; only the filter line missed it.

Fix

Coerce defensively with str(ext.get("name", "")).lower(), matching that sibling block. A bad-named entry simply fails to match, producing a clean not-found error instead of a traceback. Same bug class as the presets fix in #3743.

Testing

Adds test_add_by_name_tolerates_non_string_catalog_name, which invokes extension info <name> against a mocked catalog whose search result has name: 123. It fails pre-fix with AttributeError and passes after; the existing display-name resolution test stays green.

🤖 Generated with Claude Code
@

_resolve_catalog_extension() filters catalog search results by display
name with `ext["name"].lower() == argument.lower()`. Extension catalog
JSON is user-editable, so a hand-authored non-string name (e.g.
`name: 123`) crashes the filter with `AttributeError: 'int' object has
no attribute 'lower'`, taking down `extension info <name>` and
`extension add <name>`. A missing `name` key would likewise KeyError.

Coerce defensively with `str(ext.get("name", "")).lower()`, matching the
ambiguous-match display block just below (which already str()-coerces
name for the same reason). A bad-named entry simply doesn't match,
yielding a clean not-found error instead of a traceback.

Adds a regression test invoking `extension info <name>` against a
mocked catalog whose search result has `name: 123`; it fails pre-fix
with AttributeError.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Noor-ul-ain001
Noor-ul-ain001 requested a review from mnriem as a code owner July 26, 2026 06:56
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.

1 participant