{"record":{"id":"b02d22cc72cfdbb8","repo":"bmad-code-org/BMAD-METHOD","slug":"set-entry-empty-module-or-key-expected-m","errorCode":null,"errorMessage":"--set \"${entry}\": empty module or key. Expected <module>.<key>=<value>","messagePattern":"--set \"(.+?)\": empty module or key\\. Expected <module>\\.<key>=<value>","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"tools/installer/set-overrides.js","lineNumber":55,"sourceCode":"    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\n * that bypass `parseSetEntry`'s name check still can't pollute prototypes.\n *\n * @param {string[]} entries\n * @returns {Object<string, Object<string, string>>}\n */","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/bmad-code-org/BMAD-METHOD/blob/b70486b9bdcb0a404d329e2a763b57964e7f1360/tools/installer/set-overrides.js#L37-L73","documentation":"Thrown by parseSetEntry when the LHS splits on '.' but either side trims to empty. The format requires both module and key to be non-empty identifiers; whitespace-only or missing segments are rejected.","triggerScenarios":"Passing --set .key=value (empty module), --set module.=value (empty key), or --set module.   =value (whitespace-only key).","commonSituations":"Leading/trailing dot typo; whitespace sneaking in via copy-paste; a templating layer emitting 'module.${field}' with field unset.","solutions":["Ensure both the module and key segments are non-empty identifiers.","Remove stray dots or stray whitespace around the dot.","If generating args from a template, validate each field is populated before emitting."],"exampleFix":"# before\n#   --set .project_knowledge=research     # empty module\n#   --set bmm.=research                     # empty key\n#\n# after\n#   --set bmm.project_knowledge=research","handlingStrategy":"validation","validationCode":"function hasNonEmptyModuleAndKey(entry) {\n  const eq = entry.indexOf('='); if (eq === -1) return false;\n  const lhs = entry.slice(0, eq);\n  const dot = lhs.indexOf('.'); if (dot === -1) return false;\n  return lhs.slice(0, dot).trim().length > 0 && lhs.slice(dot + 1).trim().length > 0;\n}\nconst entries = raw.filter(hasNonEmptyModuleAndKey);","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 (/empty module or key/.test(e.message)) {\n    // strip entries with stray dots/whitespace and retry\n  } else { throw e; }\n}","preventionTips":["Trim and validate both segments of the LHS in your wrapper before emitting --set.","Avoid leading/trailing dots and whitespace in module/key identifiers."],"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"}