affaan-m/ECC · error · Error
spec. is required
Error message
spec.${key} is required What it means
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.
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.
Example fix
// before
const spec = { file: 'NDA', short: '' };
// after
const spec = { file: 'NDA', short: 'NDA-2026', role: 'consultant' }; Defensive patterns
Strategy: validation
Validate before calling
const REQUIRED = ['file', 'short', 'role'];
const missing = REQUIRED.filter(k => typeof spec?.[k] !== 'string' || spec[k].trim() === '');
if (missing.length) throw new Error(`spec missing: ${missing.join(', ')}`); Type guard
function hasRequiredSpecFields(spec) {
return typeof spec === 'object' && spec !== null &&
['file', 'short', 'role'].every(k => typeof spec[k] === 'string' && spec[k].trim() !== '');
} Try / catch
try {
buildValues(spec, now);
} catch (e) {
if (/^spec\.[a-z]+ is required$/.test(e.message)) {
console.error(`Incomplete spec: ${e.message}`);
} else throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- -32602
- a claim token is required
- a confirmed nonempty coordinate is required
- a generated candidate cannot claim original-source identity
- A managed install plan with operations is required.
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/2c268751fd95bf7f.
Report an issue: GitHub.
Appendix: source
Thrown at skills/master-agreement-generator/scripts/build-agreement.js:85
const cells = Array.from(row, (cell, cellIndex) => {
if (!Object.hasOwn(row, cellIndex) ||
!((typeof cell === 'string' && !/\p{Surrogate}/u.test(cell)) ||
(typeof cell === 'number' && Number.isFinite(cell)))) {
throw new Error(`spec.schedule[${rowIndex}][${cellIndex}] must be valid Unicode text or a finite number`);
}
return encodeScheduleCell(cell);
});
return `| ${cells.join(' | ')} |`;
}).join('\n');
}
function buildValues(spec, now) {
if (!spec || typeof spec !== 'object') {
throw new Error('spec must be an object');
}
for (const key of ['file', 'short', 'role']) {
if (typeof spec[key] !== 'string' || spec[key].trim() === '') {
throw new Error(`spec.${key} is required`);
}
}
// Reject path syntax on every host, including Windows paths supplied on POSIX.
if (/[<>:"/\\|?*\p{Cc}]/u.test(spec.file) ||
/[. ]$/.test(spec.file) ||
/^(con|prn|aux|nul|com[1-9¹²³]|lpt[1-9¹²³])(?:\.|$)/i.test(spec.file)) {
throw new Error('spec.file must be a portable filename without path components or control characters');
}
const clauses = ROLE_CLAUSES[spec.role];
if (!clauses) {
throw new Error(`unknown role "${spec.role}"; expected one of ${Object.keys(ROLE_CLAUSES).join(', ')}`);
}
const cp = spec.short;
const fill = text => text.split('{cp}').join(cp);
const supplement = typeof spec.supplement === 'string' && spec.supplement.trim() ? `${spec.supplement.trim()}; ` : '';
return {
FEE_TITLE: clauses.title,View on GitHub (pinned to 8321021c54)