{"record":{"id":"817c944297cd6740","repo":"github/spec-kit","slug":"invalid-yaml-in-bundle-yml-inside-candidate","errorCode":null,"errorMessage":"Invalid YAML in bundle.yml inside '{candidate}': {exc}","messagePattern":"Invalid YAML in bundle\\.yml inside '(.+?)': (.+?)","errorType":"exception","errorClass":"BundlerError","httpStatus":null,"severity":"error","filePath":"src/specify_cli/commands/bundle/__init__.py","lineNumber":812,"sourceCode":"        # treatment as yamlio.load_yaml: decode as UTF-8 explicitly —\n        # feeding PyYAML the byte stream would let its Reader auto-detect\n        # a UTF-16 BOM and accept a manifest the directory and bundle.yml\n        # sources reject.\n        try:\n            text = raw.decode(\"utf-8\")\n        except UnicodeError as exc:\n            raise BundlerError(\n                f\"Could not read bundle.yml inside '{candidate}': {exc}\"\n            ) from exc\n        try:\n            data = _yaml.safe_load(text)\n        except _yaml.YAMLError as exc:\n            # The sibling directory/bundle.yml branches reach YAML through\n            # load_yaml(), which turns a parse failure into a BundlerError. This\n            # branch parses inline, so without this it raises a raw YAMLError --\n            # neither a ValueError nor an OSError -- which escapes\n            # bundle_install()'s `except BundlerError` as a traceback.\n            raise BundlerError(\n                f\"Invalid YAML in bundle.yml inside '{candidate}': {exc}\"\n            ) from exc\n        return BundleManifest.from_dict(data)\n\n    if candidate.name == \"bundle.yml\" or candidate.suffix in (\".yml\", \".yaml\"):\n        return BundleManifest.from_file(candidate)\n\n    raise BundlerError(\n        f\"'{candidate}' is not a recognised bundle source (.zip artifact, bundle \"\n        \"directory, or bundle.yml).\"\n    )\n\n\ndef _resolve_manifest_path(path: Path | None) -> Path:\n    target = (path or Path.cwd()).resolve()\n    if target.is_dir():\n        target = target / \"bundle.yml\"\n    if not target.exists():","sourceCodeStart":794,"sourceCodeEnd":830,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/src/specify_cli/commands/bundle/__init__.py#L794-L830","documentation":"The zip branch parses bundle.yml inline with yaml.safe_load; a YAMLError (syntax error, bad indentation, duplicate keys per safe_load rules, tab characters) is converted to BundlerError. Without this wrap the raw YAMLError — neither ValueError nor OSError — would escape bundle_install()'s except BundlerError as a traceback, so this keeps error reporting on-contract.","triggerScenarios":"A bundle.yml inside a .zip with tab indentation, an unclosed quote/bracket, or malformed frontmatter; specify bundle install ./bundle.zip triggers the inline parse path.","commonSituations":"Tabs pasted from terminals, unquoted strings containing ':', flow-style lists with missing commas, hand-edited manifests zipped without validation.","solutions":["Run a local syntax check: python -c \"import yaml,sys; yaml.safe_load(open('bundle.yml'))\" and fix the reported line/column.","Replace tabs with spaces, quote values containing colons, and re-zip the artifact.","Validate the manifest outside the zip first (specify bundle install ./my-bundle with the same file) to iterate faster."],"exampleFix":"# before (bundle.yml, tab-indented)\nbundle:\n\tid: my-bundle\n\n# after\nbundle:\n  id: my-bundle","handlingStrategy":"validation","validationCode":"import yaml\n\ntext = open(\"bundle.yml\", encoding=\"utf-8\").read()\ntry:\n    yaml.safe_load(text)\nexcept yaml.YAMLError as exc:\n    raise SystemExit(f\"bundle.yml syntax error: {exc}\")","typeGuard":"def is_valid_yaml(text: str) -> bool:\n    import yaml\n    try:\n        yaml.safe_load(text)\n        return True\n    except yaml.YAMLError:\n        return False","tryCatchPattern":"try:\n    manifest = _local_manifest_source(Path(\"bundle.zip\"))\nexcept BundlerError as exc:\n    if \"Invalid YAML in bundle.yml\" in str(exc):\n        # fix the reported line, re-zip, retry\n        ...","preventionTips":["Lint bundle.yml with a YAML validator before zipping.","Use spaces (never tabs) for indentation in authored manifests."],"tags":["bundler","yaml","zip","validation"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}