affaan-m/ECC · error · Error
spec.schedule[ ][ ] must be valid Unicode text or a finite…
Error message
spec.schedule[${rowIndex}][${cellIndex}] must be valid Unicode text or a finite number What it means
Each schedule cell must be either a string with no unpaired surrogate code points (checked via /\p{Surrogate}/u) or a finite number. Cells that are holes (missing own property), booleans, null, objects, NaN/Infinity, or strings containing lone surrogates are rejected with a message pinpointing the row and cell index.
Solutions
- Coerce numeric cells with Number.isFinite checks and replace NaN/Infinity with 0 or a valid value.
- Fix lone surrogates: use Array.from(str) instead of str.slice on code-unit boundaries when trimming emoji.
- Replace null/boolean/object cells with strings ('yes'/'no', String(value)) or numbers.
- Ensure the cell exists (assign '' rather than delete) so Object.hasOwn passes.
- Pre-validate cells: typeof c === 'string' && !/\p{Surrogate}/u.test(c) || typeof c === 'number' && Number.isFinite(c).
Example fix
// before
row[3] = note.slice(0, 10); // may split an emoji -> lone surrogate
// after
row[3] = Array.from(note).slice(0, 10).join(''); // code-point-safe truncation Defensive patterns
Strategy: validation
Validate before calling
function isValidCell(c) {
return Object.hasOwn(arguments, 0) &&
((typeof c === 'string' && !/\p{Surrogate}/u.test(c)) ||
(typeof c === 'number' && Number.isFinite(c)));
}
// sanitize before build:
cells = cells.map(c => Number.isFinite(c) ? c : (c == null ? '' : String(c))); Type guard
const isValidCell = (c) =>
(typeof c === 'string' && !/\p{Surrogate}/u.test(c)) ||
(typeof c === 'number' && Number.isFinite(c)); Try / catch
try {
buildAgreement(spec);
} catch (e) {
const m = e.message.match(/spec\.schedule\[(\d+)\]\[(\d+)\]/);
if (m) {
const [i, j] = [Number(m[1]), Number(m[2])];
spec.schedule[i][j] = sanitizeCell(spec.schedule[i][j]);
return buildAgreement(spec);
}
throw e;
} Prevention
- Truncate strings with Array.from(str).slice(0, n).join('') to avoid lone surrogates from emoji.
- Guard numeric computations with Number.isFinite before assigning cells.
- Never put booleans, null, or objects in schedule cells; stringify or map them first.
- Validate all cells with isValidCell before calling build-agreement.
When it happens
Trigger: spec.schedule[0][2] = true; a cell set to NaN/Infinity from a bad computation; a cell containing a lone surrogate (e.g. '\uD800' from truncated slicing of an emoji string); a cell index deleted (Object.hasOwn fails); nested objects/arrays in a cell.
Common situations: Numeric columns computed with parseFloat returning NaN; string slicing cutting a multi-byte emoji in half; JSON round-trip turning undefined cells into holes; pasting rich data (objects) into a cell meant for plain text.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- -32602
- artifact path must be a non-empty relative path
- assets must be a nonempty list
- built an invalid spec
- Canonical session snapshot must be an object
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/ca578b53fc73c578.
Report an issue: GitHub.
Appendix: source
Thrown at skills/master-agreement-generator/scripts/build-agreement.js:71
}
function renderScheduleRows(rows) {
if (rows === undefined) {
return EMPTY_SCHEDULE_ROW;
}
if (!Array.isArray(rows)) {
throw new Error('spec.schedule must be an array of six-cell rows');
}
if (rows.length === 0) return EMPTY_SCHEDULE_ROW;
return Array.from(rows, (row, rowIndex) => {
if (!Object.hasOwn(rows, rowIndex) || !Array.isArray(row) || row.length !== 6) {
throw new Error(`spec.schedule[${rowIndex}] must be a dense six-cell array`);
}
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) ||View on GitHub (pinned to 8321021c54)