{"record":{"id":"527c35dd142a703f","repo":"affaan-m/ECC","slug":"unknown-role-spec-role-expected-one-of-object-keys-role","errorCode":null,"errorMessage":"unknown role \"${spec.role}\"; expected one of ${Object.keys(ROLE_CLAUSES).join(', ')}","messagePattern":"unknown role \"(.+?)\"; expected one of (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"skills/master-agreement-generator/scripts/build-agreement.js","lineNumber":96,"sourceCode":"\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,\n    CP_SHORT: cp,\n    DATE: spec.date || defaultDate(now),\n    CP_LEGAL: spec.legal || BLANK,\n    CP_JURIS: spec.juris || BLANK,\n    CP_ADDR: spec.addr || BLANK,\n    ROLE_CLAUSE: fill(clauses.role),\n    FEE_CLAUSE: fill(clauses.fee),\n    SCHEDULE_ROWS: renderScheduleRows(spec.schedule),\n    SUPPLEMENT_CLAUSE: supplement,\n    CP_SIGBLOCK: (spec.legal || cp).toUpperCase(),\n    CP_SIGNER: spec.signer || BLANK,","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/master-agreement-generator/scripts/build-agreement.js#L78-L114","documentation":"ROLE_CLAUSES is a fixed lookup of agreement roles; buildValues() selects the clause template by spec.role. When the role is not one of the known keys, it throws this error listing the valid alternatives. The message is dynamic: it echoes the offending role and enumerates accepted values.","triggerScenarios":"spec.role = 'Contractor' (wrong case), spec.role = 'vendor' when only e.g. consultant/employee/client exist, or role omitted-but-coerced (e.g. undefined interpolated into the message).","commonSituations":"Typo or wrong casing in the spec JSON, following outdated documentation that used a renamed role, or copying a spec from another generator with a different role taxonomy.","solutions":["Read the error message — it lists exactly which roles are accepted.","Change spec.role to one of the listed values, matching case exactly.","Check the project docs/templates for the canonical role names if the list is unfamiliar.","If the role list genuinely needs extending, add the clause to ROLE_CLAUSES in build-agreement.js rather than guessing a value."],"exampleFix":"// before\nconst spec = { file: 'NDA', short: 'NDA', role: 'Contractor' };\n// after\nconst spec = { file: 'NDA', short: 'NDA', role: 'consultant' }; // use a listed role","handlingStrategy":"validation","validationCode":"const VALID_ROLES = Object.keys(ROLE_CLAUSES); // or hardcode the known list\nif (!VALID_ROLES.includes(spec.role)) {\n  throw new Error(`role must be one of: ${VALID_ROLES.join(', ')}`);\n}","typeGuard":"function isKnownRole(role, knownRoles) {\n  return typeof role === 'string' && knownRoles.includes(role);\n}","tryCatchPattern":"try {\n  buildValues(spec, now);\n} catch (e) {\n  if (e.message.startsWith('unknown role')) {\n    console.error(`${e.message} — check spec.role casing and spelling`);\n  } else throw e;\n}","preventionTips":["Copy role names from the error message or docs exactly; they are case-sensitive.","Keep a shared constant of valid roles in your codebase instead of inlining strings in specs.","Validate spec.role with an enum in your schema (zod: z.enum([...])) before calling the library."],"tags":["validation","enum","configuration"],"backgroundTag":"invalid-enum-value","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"}