{"record":{"id":"c8a2abd95e08714a","repo":"bmad-code-org/BMAD-METHOD","slug":"set-entry-missing-expected-module-c8a2ab","errorCode":null,"errorMessage":"--set \"${entry}\": missing '.'. Expected <module>.<key>=<value>","messagePattern":"--set \"(.+?)\": missing '\\.'\\. Expected <module>\\.<key>=<value>","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"tools/installer/set-overrides.js","lineNumber":50,"sourceCode":" * @returns {{module: string, key: string, value: string}}\n * @throws {Error} on malformed input\n */\nfunction parseSetEntry(entry) {\n  if (typeof entry !== 'string' || entry.length === 0) {\n    throw new Error('--set: empty entry. Expected <module>.<key>=<value>');\n  }\n  const eq = entry.indexOf('=');\n  if (eq === -1) {\n    throw new Error(`--set \"${entry}\": missing '='. Expected <module>.<key>=<value>`);\n  }\n  const lhs = entry.slice(0, eq);\n  // Note: only the LHS is trimmed. Values may legitimately contain leading\n  // or trailing whitespace (paths with spaces, quoted strings); module / key\n  // names cannot, so it's safe to be strict on the left.\n  const value = entry.slice(eq + 1);\n  const dot = lhs.indexOf('.');\n  if (dot === -1) {\n    throw new Error(`--set \"${entry}\": missing '.'. Expected <module>.<key>=<value>`);\n  }\n  const moduleCode = lhs.slice(0, dot).trim();\n  const key = lhs.slice(dot + 1).trim();\n  if (!moduleCode || !key) {\n    throw new Error(`--set \"${entry}\": empty module or key. Expected <module>.<key>=<value>`);\n  }\n  if (PROTOTYPE_POLLUTING_NAMES.has(moduleCode) || PROTOTYPE_POLLUTING_NAMES.has(key)) {\n    throw new Error(\n      `--set \"${entry}\": '__proto__', 'prototype', and 'constructor' are reserved and cannot be used as a module or key name.`,\n    );\n  }\n  return { module: moduleCode, key, value };\n}\n\n/**\n * Parse repeated `--set` entries into a `{ module: { key: value } }` map.\n * Later entries overwrite earlier ones for the same key. Both the outer\n * map and the per-module inner maps are `Object.create(null)` so callers","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/bmad-code-org/BMAD-METHOD/blob/b70486b9bdcb0a404d329e2a763b57964e7f1360/tools/installer/set-overrides.js#L32-L68","documentation":"Thrown by parseSetEntry when the LHS (before '=') has no '.' separator, so it can't be split into module and key. The <module>.<key> shape is mandatory; a bare identifier has no module scope.","triggerScenarios":"Passing --set project_knowledge=research (no module prefix) or --set bmm=research (no key, no dot).","commonSituations":"User omits the module code; typo on the dot; copy-paste from docs that used a shorthand; assuming the currently installed module is implicit.","solutions":["Prefix the key with the module code and a dot: bmm.project_knowledge=research.","Verify the module code against _bmad/manifest.json or the directory name under _bmad/."],"exampleFix":"# before\n#   --set project_knowledge=research\n#\n# after\n#   --set bmm.project_knowledge=research","handlingStrategy":"validation","validationCode":"function hasModuleDot(entry) {\n  const eq = entry.indexOf('=');\n  if (eq === -1) return false;\n  return entry.slice(0, eq).indexOf('.') !== -1;\n}\nconst entries = raw.filter(hasModuleDot);","typeGuard":"function isValidSetEntry(entry) {\n  return typeof entry === 'string' && /^[^.\\s]+\\.[^.\\s]+=.+$/.test(entry);\n}","tryCatchPattern":"try {\n  overrides = parseSetEntries(entries);\n} catch (e) {\n  if (/missing '.'/.test(e.message)) {\n    // ask the user for the module prefix and re-emit\n  } else { throw e; }\n}","preventionTips":["Always qualify keys with their module code (bmm.key, core.key).","Cross-check the module code against _bmad/manifest.json before emitting --set args."],"tags":["cli","set-overrides","argument-parsing"],"backgroundTag":null,"analyzedSha":"b70486b9bdcb0a404d329e2a763b57964e7f1360","analyzedAt":"2026-08-13T01:21:12.247Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}