github/spec-kit · error · TemplateResolutionError

Failed to parse preset manifest {manifest_path}: {exc}

Error message

Failed to parse preset manifest {manifest_path}: {exc}

What it means

Raised while resolving a template preset: the preset's manifest file (YAML) under the preset directory could not be read or parsed. The loader catches OSError, UnicodeError, ValueError, and yaml.YAMLError and re-raises them as TemplateResolutionError with the offending manifest path, so any unreadable, non-UTF-8, or syntactically invalid manifest surfaces here.

Source

Thrown at scripts/python/common.py:438

                    entry.get("name") != template_name
                    or entry.get("type", "template") != "template"
                ):
                    continue
                file_value = entry.get("file", "")
                strategy = entry.get("strategy", "replace")
                relative = Path(file_value)
                if (
                    not relative
                    or relative.is_absolute()
                    or ".." in relative.parts
                ):
                    return None
                candidate = preset_dir / relative
                if not candidate.is_file():
                    return None
                return candidate, strategy.lower()
        except (OSError, UnicodeError, ValueError, yaml.YAMLError) as exc:
            raise TemplateResolutionError(
                f"Failed to parse preset manifest {manifest_path}: {exc}"
            ) from exc

    return (conventional, "replace") if conventional is not None else None


def resolve_template_content(template_name: str, repo_root: Path) -> str | None:
    """Resolve and compose template content through the project layer stack."""
    if not _is_safe_component(template_name):
        return None

    layers: list[tuple[Path, str]] = []

    def compose_from_base() -> str:
        try:
            content = layers[-1][0].read_bytes().decode("utf-8")
            for path, strategy in reversed(layers[:-1]):
                layer_content = path.read_bytes().decode("utf-8")

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Run python -c "import yaml,sys; yaml.safe_load(open(sys.argv[1]))" <manifest_path> to get the exact YAML error location and fix it.
  2. Confirm the file is valid UTF-8 (file <manifest> / re-save as UTF-8 without BOM).
  3. Check file permissions/readability of the preset directory if the message shows an OSError instead of a parser error.
  4. If the preset is not yours, delete or move the broken preset directory out of the preset stack so resolution skips it.

Example fix

# before (manifest.yaml — tab indentation breaks YAML)
strategy:	prepend
# after
strategy: prepend
Defensive patterns

Strategy: validation

Validate before calling

import yaml
from pathlib import Path

def manifest_is_loadable(path: Path) -> bool:
    try:
        raw = path.read_bytes().decode("utf-8")
        value = yaml.safe_load(raw)
        return isinstance(value, dict)
    except (OSError, UnicodeError, ValueError, yaml.YAMLError):
        return False

# skip broken presets before calling resolve_template_content
for m in preset_dir.glob("*/manifest.yaml"):
    if not manifest_is_loadable(m):
        print(f"skipping unreadable manifest: {m}")

Try / catch

try:
    content = resolve_template_content(name, repo_root)
except TemplateResolutionError as exc:
    if "Failed to parse preset manifest" in str(exc):
        logger.warning("skipping template %s: bad preset manifest (%s)", name, exc)
        content = None
    else:
        raise

Prevention

When it happens

Trigger: A preset directory (e.g. .specify/templates/presets/<name>/) contains a manifest.yaml with a YAML syntax error (bad indentation, unclosed quote, tabs), is saved in a non-UTF-8 encoding, or has file permissions that make read() raise OSError. Occurs whenever resolve_template_content() walks the preset layer stack and hits that manifest.

Common situations: Hand-editing a preset manifest and breaking YAML syntax; copying a preset from Windows with a BOM/latin-1 encoding; a manifest deleted or chmod'd between directory listing and read; CI checkout with mangled line endings producing an unparseable scalar.

Understand the failure class

Related errors


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