fix(bundle): surface a clean BundlerError on a malformed bundle download URL#3586
Merged
mnriem merged 1 commit intoJul 17, 2026
Merged
Conversation
…oad URL `_download_manifest` and its `_require_https` helper parsed the catalog entry's `download_url` with an unguarded `urlparse(url)`. A malformed authority — e.g. an unclosed IPv6 bracket like `https://[::1` — makes `urlparse` (or `.hostname` on older Pythons) raise a raw `ValueError`. The three `bundle` CLI commands (`info`, `install`, `update`) only catch `BundlerError`, so that `ValueError` escaped as an uncaught traceback. Wrap both parse sites in the same `try/except ValueError -> BundlerError` guard already used by the sibling `_validate_remote_url` (and established by the merged catalog-URL fix github#3576), so a bad `download_url` reports a clean, actionable error in every mode. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds domain-specific error handling for malformed bundle download URLs, preventing raw ValueError tracebacks.
Changes:
- Converts URL parsing failures into clean
BundlerErrormessages. - Adds regression coverage for malformed IPv6 authorities.
Show a summary per file
| File | Description |
|---|---|
src/specify_cli/commands/bundle/__init__.py |
Guards URL parsing and hostname validation. |
tests/unit/test_bundle_download_url.py |
Tests malformed URLs across both affected helpers. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 2/2 changed files
- Comments generated: 0
- Review effort level: Medium
Collaborator
|
Thank you! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
_download_manifest(and its_require_httpshelper) insrc/specify_cli/commands/bundle/__init__.pyparsed the catalog entry'sdownload_urlwith an unguardedurlparse(url). A malformed authority —e.g. an unclosed IPv6 bracket like
https://[::1— makesurlparse(or.hostnameon older Python versions) raise a rawValueError.The three
bundleCLI commands (info,install,update) wrap_download_manifestinexcept BundlerErroronly, so thatValueErrorescaped as an uncaught traceback instead of the clean error the rest of the
bundle subsystem produces.
This wraps both parse sites in the same
try/except ValueError -> BundlerErrorguard already used by the sibling
_validate_remote_url(
bundler/services/adapters.py), whose comment names this exacthttps://[::1case, and established by the merged catalog-URL fix #3576.
_require_httpsisguarded too because on older Pythons the
ValueErrorsurfaces at.hostnamerather than at
urlparse, so both are needed to keep the contract across theCI Python matrix.
Repro on
main(no network reached —offline=True):Testing
uv run specify --helpuv sync && uv run pytestI ran the affected-area tests rather than the full (slow, integration-heavy)
suite:
tests/unit/test_bundle_download_url.py(4 cases) covering both_download_manifestand_require_httpsagainsthttps://[::1andhttps://[not-an-ip]/…. It fails onmain(rawValueError) and passes withthis change (I verified red→green by stashing the fix).
tests/contract/test_bundle_cli.py+tests/unit/test_bundler_adapters.py(the direct CLI callers and the guarded sibling) — 45 passed, no
regression. The guard is a no-op for well-formed URLs (
urlparsedoesn'traise), so existing valid-URL paths are unchanged.
ruff check src/clean.AI Disclosure
This contribution is fully AI-authored and autonomous (Claude Code, acting on
this account). An AI found the bug, wrote and ran the repro, wrote the fix and
the tests, and wrote this description; the human operator of this account did
not hand-review the diff or run the tests. The verification above is real and
re-runnable from the diff — it was just done by the AI, not a person. The fix
mirrors an existing guarded sibling rather than inventing a new pattern. If
autonomous AI contributions aren't something you want to accept, say so and
I'll close this.