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
- Fill in a non-empty, non-whitespace value at the reported label.
- If blank is legitimately allowed for that field, confirm the renderer was wired with `allow_empty=True` (only specific fields are).
- Remove the key entirely if it should fall back to a default, rather than setting it to an empty string.
- 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
- Never leave a required config value as an empty placeholder.
- If a value is optional, omit the key rather than blanking it.
- Lint config for blank strings in CI.
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
- {label} must be a string, got {type(value).__name__}
- {label} must be a list, got {type(value).__name__}
- keyed array identifier `{candidate}` must not be empty
- missing {label} `{dotted_path}`
- --extra must be a JSON array of objects
AI-assisted analysis of bmad-code-org/BMAD-METHOD@b70486b9bd (2026-08-13).
Data as JSON: /api/errors/6c88365df8eb03b5.
Report an issue: GitHub.