{"record":{"id":"0d7dc67ee088ffb5","repo":"bmad-code-org/BMAD-METHOD","slug":"label-must-be-a-list-got-type-value-name","errorCode":null,"errorMessage":"{label} must be a list, got {type(value).__name__}","messagePattern":"(.+?) must be a list, got (.+?)","errorType":"validation","errorClass":"RenderError","httpStatus":null,"severity":"error","filePath":"src/scripts/render_skill.py","lineNumber":65,"sourceCode":"    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):\n        item_label = f\"{label}[{index}]\"\n        if not isinstance(item, dict):\n            raise RenderError(f\"{item_label} must be a table\")\n        identifier = _require_string(item.get(\"id\"), f\"{item_label}.id\")\n        if identifier in seen:\n            raise RenderError(f\"duplicate review layer id `{identifier}`\")","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/bmad-code-org/BMAD-METHOD/blob/b70486b9bdcb0a404d329e2a763b57964e7f1360/src/scripts/render_skill.py#L47-L83","documentation":"`_require_string_list` validates values that the renderer expects to be a list of strings (e.g. multi-item customization defaults). If the resolved value is not a Python `list` — it is a single string, a number, a bool, a dict, or None — it raises naming the label and the actual type. This is the typed-list counterpart of `_require_string` and is reached from `_resolve_customization_value` for list-typed defaults and from `_require_string_list` callers.","triggerScenarios":"A customization default expects `[\"a\",\"b\"]` but the override provides a single string `\"a\"`; a value written as an inline table instead of an array; a scalar where the template iterates; None from a missing optional layer.","commonSituations":"TOML author writes a single value where a list is required; a merge replaced an array with a scalar; a default was changed from scalar to list but the override was not updated.","solutions":["Wrap the value in an array: `tags = [\"x\"]` not `tags = \"x\"`.","If the field should accept a single string, change the consuming default/template to a scalar path (but the renderer currently routes lists through this validator, so prefer the array).","Confirm the override layer did not replace an array with a scalar during merge.","Validate the structure: `python -c \"import tomllib;print(type(tomllib.load(open('f','rb'))['k'])).\"`."],"exampleFix":"# before (customize.toml)\n[workflow]\nextra_steps = \"deploy\"     # string, but renderer wants a list\n\n# after\n[workflow]\nextra_steps = [\"deploy\"]","handlingStrategy":"type-guard","validationCode":"def list_fields_are_lists(d, list_fields):\n    return all(isinstance(d[f], list) for f in list_fields if f in d)","typeGuard":"def is_str_list(v: object) -> bool:\n    return isinstance(v, list) and all(isinstance(x, str) for x in v)","tryCatchPattern":"from render_skill import RenderError\ntry:\n    _require_string_list(value, label)\nexcept RenderError as e:\n    print(f\"error: {e}\", file=sys.stderr); sys.exit(2)","preventionTips":["Write multi-value fields as TOML arrays, even single-element ones.","Keep override layers type-consistent with their defaults.","Validate array-typed config in CI."],"tags":["render","config","type-mismatch","validation","bmad"],"backgroundTag":null,"analyzedSha":"b70486b9bdcb0a404d329e2a763b57964e7f1360","analyzedAt":"2026-08-13T01:21:12.247Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}