github/spec-kit · error · BundlerError
'requires' must be a mapping when present.
Error message
'requires' must be a mapping when present.
What it means
Raised by BundleManifest.from_dict when the manifest's optional 'requires' key is present but is not a YAML mapping. 'requires' holds speckit_version, tools, and mcp; a null/absent value defaults to empty, but any other type (string, list, scalar) is rejected instead of being silently mis-read.
Source
Thrown at src/specify_cli/bundler/models/manifest.py:118
bundle_raw = data.get("bundle")
if not isinstance(bundle_raw, dict):
raise BundlerError("Manifest is missing the required 'bundle' mapping.")
meta = BundleMeta(
id=_text(bundle_raw.get("id")),
name=_text(bundle_raw.get("name")),
version=_text(bundle_raw.get("version")),
role=_text(bundle_raw.get("role")),
description=_text(bundle_raw.get("description")),
author=_text(bundle_raw.get("author")),
license=_text(bundle_raw.get("license")),
)
requires_raw = data.get("requires")
if requires_raw is None:
requires_raw = {}
elif not isinstance(requires_raw, dict):
raise BundlerError("'requires' must be a mapping when present.")
requires = Requires(
speckit_version=_text(requires_raw.get("speckit_version")),
tools=_parse_str_list(requires_raw.get("tools"), "requires.tools"),
mcp=_parse_str_list(requires_raw.get("mcp"), "requires.mcp"),
)
integration = None
integration_raw = data.get("integration")
# Mirror the requires/provides guards above: a present-but-non-mapping
# 'integration' (e.g. a bare string "copilot") was silently dropped,
# leaving the bundle wrongly integration-agnostic. Reject it instead.
if integration_raw is not None and not isinstance(integration_raw, dict):
raise BundlerError("'integration' must be a mapping when present.")
if isinstance(integration_raw, dict) and integration_raw.get("id"):
integration = IntegrationRef(id=str(integration_raw["id"]).strip())
provides = data.get("provides")
if provides is None:View on GitHub (pinned to bf88c9f9a8)
Solutions
- Rewrite 'requires' as a mapping with the supported keys: speckit_version, tools, mcp.
- Remove the 'requires' key entirely if there are no requirements — absence is valid.
Example fix
# before (bundle.yml)
requires: "2.0"
# after
requires:
speckit_version: "2.0"
tools:
- git Defensive patterns
Strategy: type-guard
Validate before calling
def requires_shape_ok(data: dict) -> bool:
r = data.get("requires")
return r is None or isinstance(r, dict) Type guard
def is_requires_mapping(raw: object) -> bool:
return raw is None or isinstance(raw, dict) Try / catch
try:
manifest = BundleManifest.from_file(p)
except BundlerError as e:
if "'requires' must be a mapping" in str(e):
# rewrite as requires: {speckit_version: ...} or drop the key
... Prevention
- 'requires' is a mapping of speckit_version/tools/mcp — not a constraint string.
- Omit 'requires' entirely when there are no requirements.
When it happens
Trigger: A manifest contains 'requires: "^1.0"' or 'requires: [git]' (string/list) instead of a mapping like 'requires: {speckit_version: ...}'. Any parse of that manifest via BundleManifest.from_dict raises.
Common situations: Writing the version constraint directly under 'requires:' instead of 'requires: speckit_version:'; confusing the manifest schema with package.json-style requirements; hand-authoring a first bundle.
Related errors
- Manifest must be a YAML mapping at the top level.
- Manifest is missing the required 'bundle' mapping.
- 'integration' must be a mapping when present.
- 'provides' must be a mapping when present.
- '{field_name}' must be a list of strings when present.
AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14).
Data as JSON: /api/errors/49892e94196ea6e1.
Report an issue: GitHub.