{"record":{"id":"010d06e01c097782","repo":"github/spec-kit","slug":"catalog-entry-resolved-entry-id-has-no-downloa","errorCode":null,"errorMessage":"Catalog entry '{resolved.entry.id}' has no download_url; cannot resolve its manifest.","messagePattern":"Catalog entry '(.+?)' has no download_url; cannot resolve its manifest\\.","errorType":"exception","errorClass":"BundlerError","httpStatus":null,"severity":"error","filePath":"src/specify_cli/commands/bundle/__init__.py","lineNumber":853,"sourceCode":"def _download_manifest(resolved, *, offline: bool):\n    \"\"\"Resolve a bundle's manifest from its catalog ``download_url``.\n\n    Catalog ``download_url``s are HTTPS-only (``http`` allowed for localhost),\n    matching the extensions/presets/workflows catalog systems. Remote URLs are\n    fetched with the shared authenticated, redirect-validated HTTP client, and\n    only when not ``--offline``.\n\n    Local and ``file://`` sources are intentionally not resolved here: to\n    install a bundle from disk, pass the path positionally\n    (``specify bundle install ./path/to/bundle.yml`` — a bundle directory or a\n    ``.zip`` artifact also works), which :func:`_local_manifest_source` handles\n    before catalog resolution and which never touches ``download_url``.\n    \"\"\"\n    from urllib.parse import urlparse\n\n    url = resolved.entry.download_url\n    if not url:\n        raise BundlerError(\n            f\"Catalog entry '{resolved.entry.id}' has no download_url; cannot resolve \"\n            \"its manifest.\"\n        )\n    # A malformed authority (e.g. an unclosed IPv6 bracket ``https://[::1``)\n    # makes urlparse raise ValueError. Surface it as the documented\n    # BundlerError, like the sibling ``_validate_remote_url``, rather than\n    # leaking a raw ValueError past the callers, which only catch BundlerError.\n    try:\n        parsed = urlparse(url)\n    except ValueError:\n        raise BundlerError(\n            f\"Catalog entry '{resolved.entry.id}' has a malformed download_url: {url}\"\n        ) from None\n    scheme = parsed.scheme.lower()\n\n    # ``file://`` URLs and bare filesystem paths (including Windows drive paths\n    # like ``C:\\bundle.yml``, which urlparse reads as a single-letter scheme)\n    # are not valid catalog download URLs. Catalog URLs are HTTPS-only across","sourceCodeStart":835,"sourceCodeEnd":871,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/src/specify_cli/commands/bundle/__init__.py#L835-L871","documentation":"_download_manifest fetches a catalog-resolved bundle's manifest from its entry.download_url; this fires when the catalog entry carries no download_url at all, so there is nothing to fetch. It is a data-quality error in the catalog (or its cached copy), not in the user's project.","triggerScenarios":"stack.resolve(bundle_id) succeeds and _download_manifest is called, but resolved.entry.download_url is falsy — a registry row published without a download link.","commonSituations":"Curated catalogs with incomplete entries; hand-edited catalog JSON/YAML missing the field; a bundle indexed for discovery only but accidentally resolvable from an install-allowed source.","solutions":["Install from a concrete artifact instead: specify bundle install <bundle.yml | dir | .zip>.","Fix the catalog entry by adding its download_url and refresh/re-cache the catalog.","Report to the catalog maintainer if it is a third-party index."],"exampleFix":"# before (catalog entry)\n{\"id\": \"my-bundle\", \"name\": \"My Bundle\"}\n\n# after\n{\"id\": \"my-bundle\", \"name\": \"My Bundle\", \"download_url\": \"https://example.com/my-bundle.zip\"}","handlingStrategy":"validation","validationCode":"resolved = stack.resolve(bundle_id)\nif not resolved.entry.download_url:\n    raise SystemExit(f\"Catalog entry '{resolved.entry.id}' lacks download_url; install from a path instead\")","typeGuard":"def entry_is_downloadable(resolved) -> bool:\n    return bool(getattr(resolved.entry, \"download_url\", None))","tryCatchPattern":"try:\n    manifest = _download_manifest(resolved, offline=offline)\nexcept BundlerError as exc:\n    if \"no download_url\" in str(exc):\n        # install from local artifact; report catalog data issue\n        ...","preventionTips":["Validate catalog entries (download_url present and https) at publish time.","Keep local artifact copies of catalog bundles you depend on."],"tags":["bundler","catalog","download","data-quality"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}