github/spec-kit · error · PresetValidationError

Wrap strategy in '{layer['source']}' is missing the {placeho

Error message

Wrap strategy in '{layer['source']}' is missing the {placeholder} placeholder. The wrapper must contain {placeholder} to indicate where the lower-priority content should be inserted.

What it means

A preset layer using the 'wrap' merge strategy does not contain the required placeholder marking where lower-priority content goes: '$CORE_SCRIPT' for script templates, '{CORE_TEMPLATE}' for others. Without the placeholder the substitution target is undefined, so layer composition raises PresetValidationError instead of guessing.

Source

Thrown at src/specify_cli/presets/__init__.py:5851

                if strategy == "replace":
                    top_frontmatter_text = fm
                    base_frontmatter_text = fm
                elif fm:
                    top_frontmatter_text = fm

            if strategy == "replace":
                content = layer_content
            elif strategy == "prepend":
                content = layer_content + "\n\n" + content
            elif strategy == "append":
                content = content + "\n\n" + layer_content
            elif strategy == "wrap":
                if template_type == "script":
                    placeholder = "$CORE_SCRIPT"
                else:
                    placeholder = "{CORE_TEMPLATE}"
                if placeholder not in layer_content:
                    raise PresetValidationError(
                        f"Wrap strategy in '{layer['source']}' is missing "
                        f"the {placeholder} placeholder. The wrapper must "
                        f"contain {placeholder} to indicate where the "
                        f"lower-priority content should be inserted."
                    )
                content = layer_content.replace(placeholder, content)

        # Reattach the highest-priority frontmatter for commands,
        # inheriting scripts/agent_scripts from the base if missing
        # and stripping the strategy key (internal-only, not for agent output).
        if is_command and top_frontmatter_text:
            def _parse_fm_yaml(fm_block: str) -> dict:
                """Parse YAML from a frontmatter block (with --- fences)."""
                lines = fm_block.splitlines()
                # Parse only interior lines (between --- fences)
                if len(lines) >= 2:
                    yaml_lines = lines[1:-1]
                else:

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Add the correct placeholder to the wrapper: $CORE_SCRIPT in script layers, {CORE_TEMPLATE} in markdown/command layers
  2. Check placeholder spelling and braces exactly — {CORE_TEMPLATE} uses braces, $CORE_SCRIPT uses a dollar prefix
  3. If you intended full replacement rather than wrapping, change the layer strategy to 'replace'

Example fix

# before (markdown wrap layer)
strategy: wrap
---
# My wrapper header
<!-- no placeholder -->

# after
strategy: wrap
---
# My wrapper header
{CORE_TEMPLATE}
Defensive patterns

Strategy: validation

Validate before calling

placeholder = "$CORE_SCRIPT" if template_type == "script" else "{CORE_TEMPLATE}"
if layer["strategy"] == "wrap" and placeholder not in layer_content:
    raise ValueError(f"wrap layer '{source}' missing {placeholder}")

Type guard

def wrap_layer_is_valid(layer_content: str, template_type: str) -> bool:
    ph = "$CORE_SCRIPT" if template_type == "script" else "{CORE_TEMPLATE}"
    return ph in layer_content

Try / catch

except PresetValidationError as e:
    if "missing the" in str(e) and "placeholder" in str(e):
        # report the layer source and expected placeholder to the author
        raise PresetAuthoringError(layer_source, str(e)) from e
    raise

Prevention

When it happens

Trigger: Authoring a preset overlay/extension template with strategy: wrap whose wrapper content omits $CORE_SCRIPT (scripts) or {CORE_TEMPLATE} (markdown/command templates); encountered during template layer merging.

Common situations: Copy-pasting a non-wrap template into a wrap layer; renaming or removing the placeholder while restyling a wrapper; using {CORE_TEMPLATE} in a script file (or $CORE_SCRIPT in markdown) so the type-specific placeholder is missing.

Related errors


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