github/spec-kit · error · BundlerError

Network access disabled; cannot download bundle '{resolved.e

Error message

Network access disabled; cannot download bundle '{resolved.entry.id}' from {url}.

What it means

The offline gate in _download_manifest: the catalog entry's download_url is a valid remote HTTPS URL, but the command was run with --offline (or allow_network is otherwise disabled), so the manifest cannot be downloaded. The scheme/host were validated first, so this message means the URL is fine — only the network prohibition blocks it.

Source

Thrown at src/specify_cli/commands/bundle/__init__.py:893

    if scheme in ("", "file") or re.match(r"^[A-Za-z]:[\\/]", url):
        raise BundlerError(
            f"Catalog entry '{resolved.entry.id}' has a non-HTTP(S) download_url "
            f"({url}); catalog download URLs must be HTTPS (http for localhost) — "
            "a file:// URL, a local filesystem path, or a scheme-less value "
            "(e.g. 'example.com/bundle.zip') is not accepted. "
            "To install a bundle from disk, pass the path directly: "
            "'specify bundle install <path-to-bundle.yml | bundle-dir | .zip>'."
        )

    # Validate the scheme/host *before* the offline gate so an invalid or
    # non-HTTPS download_url reports the real problem in every mode, rather
    # than a misleading "Network access disabled" under --offline.
    # (_download_remote_manifest re-checks this, but only once network access
    # is permitted.) HTTPS-only, http allowed for localhost.
    _require_https(f"bundle '{resolved.entry.id}'", url)

    if offline:
        raise BundlerError(
            f"Network access disabled; cannot download bundle '{resolved.entry.id}' "
            f"from {url}."
        )
    manifest = _download_remote_manifest(
        resolved.entry.id,
        url,
        expected_sha256=getattr(resolved.entry, "sha256", None),
    )
    _validate_catalog_manifest(resolved.entry, manifest)
    return manifest


def _require_https(label: str, url: str) -> None:
    from urllib.parse import urlparse

    # urlparse / hostname access raise ValueError on a malformed authority;
    # keep the documented BundlerError contract (older Pythons surface this via
    # the .hostname access below rather than at the urlparse call).

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Pre-fetch the artifact on a networked machine and install from disk: specify bundle install ./bundle.zip (or the bundle dir / bundle.yml).
  2. Drop --offline if network access is actually allowed.
  3. For repeated offline installs, mirror the bundle as a local file source and pass its path.

Example fix

# before
specify bundle install my-bundle --offline

# after
# (on a networked machine) download the artifact, then offline:
specify bundle install ./my-bundle.zip --offline
Defensive patterns

Strategy: fallback

Validate before calling

if offline and resolved.entry.download_url and not resolved.source.is_local:
    raise SystemExit("Offline mode cannot fetch remote manifests; install from ./bundle.zip instead")

Try / catch

try:
    manifest = _download_manifest(resolved, offline=offline)
except BundlerError as exc:
    if "Network access disabled" in str(exc):
        # fallback: install from a pre-fetched local artifact path
        ...

Prevention

When it happens

Trigger: specify bundle install <catalog-id> --offline (or bundle update --offline) where the bundle resolves to a remote catalog entry with a download_url; there is no local cache path for catalog manifests.

Common situations: Air-gapped or firewalled machines; CI jobs pinned to --offline for determinism; users trying to avoid surprise downloads.

Related errors


AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14). Data as JSON: /api/errors/e971eb4bf030ac0d. Report an issue: GitHub.