{"record":{"id":"687a9b97a92f32dd","repo":"bmad-code-org/BMAD-METHOD","slug":"ambiguous-config-value-key-found-at-paths","errorCode":null,"errorMessage":"ambiguous config value `{key}` found at: {paths}","messagePattern":"ambiguous config value `(.+?)` found at: (.+?)","errorType":"exception","errorClass":"RenderError","httpStatus":null,"severity":"error","filePath":"src/scripts/render_skill.py","lineNumber":148,"sourceCode":"    if not isinstance(data, dict):\n        return matches\n    for name, value in data.items():\n        path = f\"{prefix}.{name}\" if prefix else name\n        if name == key and not isinstance(value, (dict, list)):\n            matches.append((path, value))\n        matches.extend(_find_config_values(value, key, path))\n    return matches\n\n\ndef _resolve_short_config(\n    central: dict[str, Any], key: str, project_root: Path\n) -> tuple[str, str]:\n    matches = _find_config_values(central, key)\n    if not matches:\n        raise RenderError(f\"missing config value `{key}`\")\n    if len(matches) > 1:\n        paths = \", \".join(path for path, _ in matches)\n        raise RenderError(f\"ambiguous config value `{key}` found at: {paths}\")\n    path, value = matches[0]\n    return path, _resolve_config_value(value, f\"config.{path}\", project_root)\n\n\ndef _format_markdown_list(items: list[str]) -> str:\n    if not items:\n        return \"_None._\"\n    rendered = []\n    for item in items:\n        lines = item.splitlines() or [\"\"]\n        rendered.append(\"- \" + lines[0])\n        rendered.extend(\"  \" + line for line in lines[1:])\n    return \"\\n\".join(rendered)\n\n\ndef _format_review_layers(layers: list[dict[str, str]]) -> str:\n    active = [layer for layer in layers if layer[\"instruction\"].strip()]\n    if not active:","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/bmad-code-org/BMAD-METHOD/blob/b70486b9bdcb0a404d329e2a763b57964e7f1360/src/scripts/render_skill.py#L130-L166","documentation":"The short-config resolver requires exactly one match for {{.key}} across the whole central config tree. If the same terminal key name appears in multiple sections (e.g. project.name and team.name), it cannot choose deterministically and aborts, listing every location found.","triggerScenarios":"Source uses {{.name}}; central config contains both [project] name=... and [team] name=... . _find_config_values returns two matches, so _resolve_short_config raises with the dotted paths joined by commas.","commonSituations":"Reusing common key names (name, id, version, path) across multiple TOML sections; merging several config layers that each define a same-named leaf.","solutions":["Switch the token to the explicit dotted form {{config.section.name}}.","Rename one of the colliding keys so only one match remains.","Use the full dotted paths reported in {paths} to disambiguate."],"exampleFix":"# before: {{.name}} is ambiguous between project.name and team.name\n# after: use the explicit path\n{{config.project.name}}","handlingStrategy":"validation","validationCode":"import re, tomllib\nfrom pathlib import Path\n\nSHORT = re.compile(r\"\\{\\{\\.([A-Za-z0-9_]+)\\}\\}\")\n\ndef find_keys(obj, prefix=\"\") -> list[str]:\n    out: list[str] = []\n    if isinstance(obj, dict):\n        for k, v in obj.items():\n            path = f\"{prefix}.{k}\" if prefix else k\n            if not isinstance(v, (dict, list)):\n                out.append(path)\n            out += find_keys(v, path)\n    return out\n\ndef validate_short_tokens_unambiguous(sources: dict[str,str], central_path: Path) -> None:\n    central = tomllib.loads(Path(central_path).read_text(encoding=\"utf-8\"))\n    all_paths = find_keys(central)\n    for txt in sources.values():\n        for m in SHORT.finditer(txt):\n            key = m.group(1)\n            hits = [p for p in all_paths if p.split(\".\")[-1] == key]\n            if len(hits) > 1:\n                raise SystemExit(f\"ambiguous {key}: {hits}\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Avoid reusing common leaf names (name, id, version) across sections when using short tokens.","Switch ambiguous tokens to the dotted {{config.section.key}} form.","Lint for duplicate terminal keys in central config."],"tags":["python","config","toml","token","validation","ambiguity"],"backgroundTag":null,"analyzedSha":"b70486b9bdcb0a404d329e2a763b57964e7f1360","analyzedAt":"2026-08-13T01:21:12.247Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}