github/spec-kit · error · BundlerError

Downloaded artifact for bundle '{entry_id}' from {_source_de

Error message

Downloaded artifact for bundle '{entry_id}' from {_source_desc} is not a valid bundle: {exc}

What it means

The downloaded bytes were identified as a ZIP archive, either because the catalog URL ends in .zip or the payload starts with a ZIP signature, but extracting its manifest failed. Spec Kit writes the payload to a temporary file and reuses the local bundle reader, which requires a readable archive containing a root-level bundle.yml.

Source

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

    # Detection uses the path component of the original catalog URL (via
    # PurePosixPath so query strings and fragments are ignored, and URL paths
    # are always treated as POSIX regardless of host OS), falling back to the
    # module-level _ZIP_SIGNATURES magic-byte check for direct REST API asset
    # URLs which carry no file extension.
    _url_ext = PurePosixPath(_urlparse(url).path).suffix.lower()
    try:
        if _url_ext == ".zip" or raw[:4] in _ZIP_SIGNATURES:
            with tempfile.TemporaryDirectory() as tmp:
                artifact = Path(tmp) / "bundle.zip"
                artifact.write_bytes(raw)
                # Wrap ZIP parsing so any failure (BadZipFile, missing
                # bundle.yml, etc.) references the source URL rather than the
                # opaque temporary path, consistent with the download-error
                # handling above.
                try:
                    manifest = _local_manifest_source(str(artifact))
                except Exception as exc:  # noqa: BLE001
                    raise BundlerError(
                        f"Downloaded artifact for bundle '{entry_id}' from "
                        f"{_source_desc} is not a valid bundle: {exc}"
                    ) from exc
                # _local_manifest_source returns None only when the file does
                # not exist; since we just wrote *artifact* that cannot happen
                # here.  The explicit guard ensures callers never receive None
                # and silently degrade instead of raising a clear error.
                if manifest is None:
                    raise BundlerError(
                        f"Downloaded artifact for bundle '{entry_id}' from "
                        f"{_source_desc} is not a valid bundle."
                    )
                return manifest

        data = _yaml.safe_load(io.BytesIO(raw))
        return BundleManifest.from_dict(data)
    except BundlerError:
        raise

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Download the exact URL from the error and run `unzip -l <file>` to inspect the archive.
  2. Ensure `bundle.yml` is at the archive root, not under `my-bundle/` or `dist/`.
  3. Rebuild and upload the complete ZIP artifact, then update the catalog if the URL changed.
  4. If the payload is actually YAML, remove the misleading `.zip` extension from the download URL.
  5. If the response is HTML, fix authentication or the direct-asset URL before republishing.

Example fix

# archive layout (before)
my-bundle/
  bundle.yml

# archive layout (after)
bundle.yml
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path
from zipfile import ZipFile

def zip_is_valid_bundle_artifact(path: Path) -> bool:
    try:
        with ZipFile(path) as archive:
            names = set(archive.namelist())
            return "bundle.yml" in names and archive.testzip() is None
    except Exception:
        return False

Try / catch

except BundlerError as exc:
    if "is not a valid bundle" in str(exc):
        inspect_remote_zip_layout()
    else:
        raise

Prevention

When it happens

Trigger: The artifact is truncated or corrupt, bundle.yml is missing from the ZIP root, bundle.yml is nested under a directory, a ZIP member is oversized, or bundle.yml cannot be decoded/parsed. The underlying failure text is appended after the colon.

Common situations: A maintainer zipped the project directory instead of running the bundle build output, uploaded a tar.gz while naming the URL .zip, uploaded an incomplete file, or pointed a `.zip` URL at an HTML login/error page.

Related errors


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