{"record":{"id":"2c268751fd95bf7f","repo":"affaan-m/ECC","slug":"spec-key-is-required","errorCode":null,"errorMessage":"spec.${key} is required","messagePattern":"spec\\.(.+?) is required","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"skills/master-agreement-generator/scripts/build-agreement.js","lineNumber":85,"sourceCode":"    const cells = Array.from(row, (cell, cellIndex) => {\n      if (!Object.hasOwn(row, cellIndex) ||\n          !((typeof cell === 'string' && !/\\p{Surrogate}/u.test(cell)) ||\n            (typeof cell === 'number' && Number.isFinite(cell)))) {\n        throw new Error(`spec.schedule[${rowIndex}][${cellIndex}] must be valid Unicode text or a finite number`);\n      }\n      return encodeScheduleCell(cell);\n    });\n    return `| ${cells.join(' | ')} |`;\n  }).join('\\n');\n}\n\nfunction buildValues(spec, now) {\n  if (!spec || typeof spec !== 'object') {\n    throw new Error('spec must be an object');\n  }\n  for (const key of ['file', 'short', 'role']) {\n    if (typeof spec[key] !== 'string' || spec[key].trim() === '') {\n      throw new Error(`spec.${key} is required`);\n    }\n  }\n  // Reject path syntax on every host, including Windows paths supplied on POSIX.\n  if (/[<>:\"/\\\\|?*\\p{Cc}]/u.test(spec.file) ||\n      /[. ]$/.test(spec.file) ||\n      /^(con|prn|aux|nul|com[1-9¹²³]|lpt[1-9¹²³])(?:\\.|$)/i.test(spec.file)) {\n    throw new Error('spec.file must be a portable filename without path components or control characters');\n  }\n  const clauses = ROLE_CLAUSES[spec.role];\n  if (!clauses) {\n    throw new Error(`unknown role \"${spec.role}\"; expected one of ${Object.keys(ROLE_CLAUSES).join(', ')}`);\n  }\n  const cp = spec.short;\n  const fill = text => text.split('{cp}').join(cp);\n  const supplement = typeof spec.supplement === 'string' && spec.supplement.trim() ? `${spec.supplement.trim()}; ` : '';\n\n  return {\n    FEE_TITLE: clauses.title,","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/master-agreement-generator/scripts/build-agreement.js#L67-L103","documentation":"After confirming spec is an object, buildValues() requires the fields file, short, and role to be non-empty trimmed strings. It throws templated 'spec.<key> is required' when any of them is missing, not a string, or whitespace-only. These fields drive the output filename, short citation form, and clause selection.","triggerScenarios":"Calling values()/buildValues() with a spec object missing e.g. role, or where spec.short is '' or '   ', or where the field is a number/boolean instead of a string.","commonSituations":"Hand-edited spec JSON with a typo'd field name (e.g. 'filename' instead of 'file'), a form/CLI that allows blank inputs, or a partial spec object constructed programmatically with defaults left undefined.","solutions":["Read the error message: it names the exact missing key (e.g. spec.role is required).","Add that key to your spec with a non-empty string value.","Trim whitespace-only values — a string of spaces still fails.","Validate the whole spec up front with a schema so all missing fields are reported at once instead of one at a time."],"exampleFix":"// before\nconst spec = { file: 'NDA', short: '' };\n// after\nconst spec = { file: 'NDA', short: 'NDA-2026', role: 'consultant' };","handlingStrategy":"validation","validationCode":"const REQUIRED = ['file', 'short', 'role'];\nconst missing = REQUIRED.filter(k => typeof spec?.[k] !== 'string' || spec[k].trim() === '');\nif (missing.length) throw new Error(`spec missing: ${missing.join(', ')}`);","typeGuard":"function hasRequiredSpecFields(spec) {\n  return typeof spec === 'object' && spec !== null &&\n    ['file', 'short', 'role'].every(k => typeof spec[k] === 'string' && spec[k].trim() !== '');\n}","tryCatchPattern":"try {\n  buildValues(spec, now);\n} catch (e) {\n  if (/^spec\\.[a-z]+ is required$/.test(e.message)) {\n    console.error(`Incomplete spec: ${e.message}`);\n  } else throw e;\n}","preventionTips":["Validate all required fields with a schema before calling the library; report all gaps at once.","Treat whitespace-only strings as missing — trim before checking.","Keep a canonical spec template in the repo so hand-edits don't drop fields."],"tags":["validation","required-fields"],"backgroundTag":"empty-required-field","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}