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

{label} must not be empty

Error message

{label} must not be empty

What it means

`_require_string` accepts a string but rejects one that is empty or whitespace-only (unless the caller passed `allow_empty=True`, which the renderer does only for `instruction` and an empty/default `open_spec`). The error names the label. It catches a value that is present and string-typed but carries no usable content, which would otherwise render as a blank in the published snapshot.

Source

Thrown at src/scripts/render_skill.py:59

    return json.dumps(
        value, ensure_ascii=False, sort_keys=True, separators=(",", ":")
    ).encode("utf-8")


def _lookup(data: dict[str, Any], dotted_path: str, label: str) -> Any:
    current: Any = data
    for part in dotted_path.split("."):
        if not isinstance(current, dict) or part not in current:
            raise RenderError(f"missing {label} `{dotted_path}`")
        current = current[part]
    return current


def _require_string(value: Any, label: str, *, allow_empty: bool = False) -> str:
    if not isinstance(value, str):
        raise RenderError(f"{label} must be a string, got {type(value).__name__}")
    if not allow_empty and not value.strip():
        raise RenderError(f"{label} must not be empty")
    return value


def _require_string_list(value: Any, label: str) -> list[str]:
    if not isinstance(value, list):
        raise RenderError(f"{label} must be a list, got {type(value).__name__}")
    result = []
    for index, item in enumerate(value):
        result.append(_require_string(item, f"{label}[{index}]"))
    return result


def _require_review_layers(value: Any, label: str) -> list[dict[str, str]]:
    if not isinstance(value, list):
        raise RenderError(f"{label} must be a list of tables")
    result: list[dict[str, str]] = []
    seen: set[str] = set()
    for index, item in enumerate(value):

View on GitHub (pinned to b70486b9bd)

Solutions

  1. Fill in a non-empty, non-whitespace value at the reported label.
  2. If blank is legitimately allowed for that field, confirm the renderer was wired with `allow_empty=True` (only specific fields are).
  3. Remove the key entirely if it should fall back to a default, rather than setting it to an empty string.
  4. Lint for blank values: `python -c "import tomllib;d=tomllib.load(open('f','rb'));..."`.

Example fix

# before (config.toml)
[project]
name = ""

# after
[project]
name = "atlas"
Defensive patterns

Strategy: validation

Validate before calling

def no_blank_strings(d, prefix=''):
    bad = []
    for k,v in d.items():
        p = f'{prefix}.{k}' if prefix else k
        if isinstance(v, dict): bad += no_blank_strings(v, p)
        elif isinstance(v, str) and not v.strip(): bad.append(p)
    return bad

Type guard

def is_nonempty_str(v: object) -> bool:
    return isinstance(v, str) and bool(v.strip())

Try / catch

from render_skill import RenderError
try:
    _require_string(value, label)
except RenderError as e:
    print(f"error: {e}", file=sys.stderr); sys.exit(2)

Prevention

When it happens

Trigger: A config/customization value set to `""` or `" "`; a required key like `project.name` left blank; a layer that explicitly blanked a value previously set elsewhere.

Common situations: A template left `name = ""` as a placeholder; a customization override that emptied a shipped default; copy-paste that dropped the value after the `=`.

Related errors


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