{"record":{"id":"6c88365df8eb03b5","repo":"bmad-code-org/BMAD-METHOD","slug":"label-must-not-be-empty","errorCode":null,"errorMessage":"{label} must not be empty","messagePattern":"(.+?) must not be empty","errorType":"validation","errorClass":"RenderError","httpStatus":null,"severity":"error","filePath":"src/scripts/render_skill.py","lineNumber":59,"sourceCode":"    return json.dumps(\n        value, ensure_ascii=False, sort_keys=True, separators=(\",\", \":\")\n    ).encode(\"utf-8\")\n\n\ndef _lookup(data: dict[str, Any], dotted_path: str, label: str) -> Any:\n    current: Any = data\n    for part in dotted_path.split(\".\"):\n        if not isinstance(current, dict) or part not in current:\n            raise RenderError(f\"missing {label} `{dotted_path}`\")\n        current = current[part]\n    return current\n\n\ndef _require_string(value: Any, label: str, *, allow_empty: bool = False) -> str:\n    if not isinstance(value, str):\n        raise RenderError(f\"{label} must be a string, got {type(value).__name__}\")\n    if not allow_empty and not value.strip():\n        raise RenderError(f\"{label} must not be empty\")\n    return value\n\n\ndef _require_string_list(value: Any, label: str) -> list[str]:\n    if not isinstance(value, list):\n        raise RenderError(f\"{label} must be a list, got {type(value).__name__}\")\n    result = []\n    for index, item in enumerate(value):\n        result.append(_require_string(item, f\"{label}[{index}]\"))\n    return result\n\n\ndef _require_review_layers(value: Any, label: str) -> list[dict[str, str]]:\n    if not isinstance(value, list):\n        raise RenderError(f\"{label} must be a list of tables\")\n    result: list[dict[str, str]] = []\n    seen: set[str] = set()\n    for index, item in enumerate(value):","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/bmad-code-org/BMAD-METHOD/blob/b70486b9bdcb0a404d329e2a763b57964e7f1360/src/scripts/render_skill.py#L41-L77","documentation":"`_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.","triggerScenarios":"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.","commonSituations":"A template left `name = \"\"` as a placeholder; a customization override that emptied a shipped default; copy-paste that dropped the value after the `=`.","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'));...\"`."],"exampleFix":"# before (config.toml)\n[project]\nname = \"\"\n\n# after\n[project]\nname = \"atlas\"","handlingStrategy":"validation","validationCode":"def no_blank_strings(d, prefix=''):\n    bad = []\n    for k,v in d.items():\n        p = f'{prefix}.{k}' if prefix else k\n        if isinstance(v, dict): bad += no_blank_strings(v, p)\n        elif isinstance(v, str) and not v.strip(): bad.append(p)\n    return bad","typeGuard":"def is_nonempty_str(v: object) -> bool:\n    return isinstance(v, str) and bool(v.strip())","tryCatchPattern":"from render_skill import RenderError\ntry:\n    _require_string(value, label)\nexcept RenderError as e:\n    print(f\"error: {e}\", file=sys.stderr); sys.exit(2)","preventionTips":["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."],"tags":["render","config","validation","empty-value","bmad"],"backgroundTag":null,"analyzedSha":"b70486b9bdcb0a404d329e2a763b57964e7f1360","analyzedAt":"2026-08-13T01:21:12.247Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}