bmad-code-org/BMAD-METHOD · error · RenderError

{label} has unsupported default type {type(default).__name__

Error message

{label} has unsupported default type {type(default).__name__}

What it means

_resolve_customization_value only supports customization defaults that are strings or lists (a list of dicts becomes review layers; a list of scalars becomes a markdown bullet list). If customize.toml declares a default that is an int, float, bool, inline table, or datetime, the renderer refuses it because it cannot render that type into markdown.

Source

Thrown at src/scripts/render_skill.py:189

        if layer.get("when"):
            section.extend(["", f"Run only when: {layer['when']}"])
        section.extend(["", layer["instruction"].strip()])
        sections.append("\n".join(section))
    return "\n\n".join(sections)


def _resolve_customization_value(value: Any, default: Any, label: str) -> tuple[Any, str]:
    if isinstance(default, str):
        allow_empty = not default.strip() or label == "customization.workflow.open_spec"
        resolved = _require_string(value, label, allow_empty=allow_empty)
        return resolved, resolved
    if isinstance(default, list):
        if default and all(isinstance(item, dict) for item in default):
            resolved = _require_review_layers(value, label)
            return resolved, _format_review_layers(resolved)
        resolved = _require_string_list(value, label)
        return resolved, _format_markdown_list(resolved)
    raise RenderError(f"{label} has unsupported default type {type(default).__name__}")


def _resolve_replacements(
    sources: dict[str, str],
    central: dict[str, Any],
    customization: dict[str, Any],
    defaults: dict[str, Any] | None,
    project_root: Path,
) -> tuple[dict[str, str], dict[str, Any]]:
    replacements: dict[str, str] = {}
    input_values: dict[str, Any] = {}
    for content in sources.values():
        for match in _SHORT_CONFIG_TOKEN.finditer(content):
            token, key = match.group(0), match.group(1)
            path, resolved = _resolve_short_config(central, key, project_root)
            source = f"config.{path}"
            replacements[token] = resolved
            input_values[source] = resolved

View on GitHub (pinned to b70486b9bd)

Solutions

  1. Change the default in customize.toml to a string (e.g. retries = "3").
  2. If a list is intended, use TOML array syntax (retries = ["a", "b"]).
  3. Remove the unsupported {workflow.*} token from sources, or restructure the default to a supported type.

Example fix

# before
[workflow]
retries = 3

# after
[workflow]
retries = "3"
Defensive patterns

Strategy: type-guard

Validate before calling

import tomllib
from pathlib import Path

def assert_supported_defaults(toml_path: Path) -> None:
    data = tomllib.loads(Path(toml_path).read_text(encoding="utf-8"))
    def walk(obj, prefix=""):
        if isinstance(obj, dict):
            for k, v in obj.items():
                walk(v, f"{prefix}.{k}" if prefix else k)
        elif not isinstance(obj, (str, list)):
            raise SystemExit(f"{prefix}: unsupported default type {type(obj).__name__}")
    walk(data)

Type guard

def is_supported_default(value: object) -> bool:
    return isinstance(value, (str, list))

Prevention

When it happens

Trigger: customize.toml has [workflow] retries = 3 (int) or flag = true (bool) or a nested [workflow.x] table that is referenced by a {workflow.retries} / {workflow.flag} token. The looked-up default is neither str nor list.

Common situations: Authoring customization with numeric or boolean settings; using a nested table default where a scalar/list was expected.

Related errors


AI-assisted analysis of bmad-code-org/BMAD-METHOD@b70486b9bd (2026-08-13). Data as JSON: /api/errors/0ba67bcc27259588. Report an issue: GitHub.