{"record":{"id":"ca578b53fc73c578","repo":"affaan-m/ECC","slug":"spec-schedule-rowindex-cellindex-must-be-valid-unicode-text","errorCode":null,"errorMessage":"spec.schedule[${rowIndex}][${cellIndex}] must be valid Unicode text or a finite number","messagePattern":"spec\\.schedule\\[(.+?)\\]\\[(.+?)\\] must be valid Unicode text or a finite number","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"skills/master-agreement-generator/scripts/build-agreement.js","lineNumber":71,"sourceCode":"}\n\nfunction renderScheduleRows(rows) {\n  if (rows === undefined) {\n    return EMPTY_SCHEDULE_ROW;\n  }\n  if (!Array.isArray(rows)) {\n    throw new Error('spec.schedule must be an array of six-cell rows');\n  }\n  if (rows.length === 0) return EMPTY_SCHEDULE_ROW;\n  return Array.from(rows, (row, rowIndex) => {\n    if (!Object.hasOwn(rows, rowIndex) || !Array.isArray(row) || row.length !== 6) {\n      throw new Error(`spec.schedule[${rowIndex}] must be a dense six-cell array`);\n    }\n    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) ||","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/master-agreement-generator/scripts/build-agreement.js#L53-L89","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before\nrow[3] = note.slice(0, 10);            // may split an emoji -> lone surrogate\n// after\nrow[3] = Array.from(note).slice(0, 10).join(''); // code-point-safe truncation","handlingStrategy":"validation","validationCode":"function isValidCell(c) {\n  return Object.hasOwn(arguments, 0) &&\n    ((typeof c === 'string' && !/\\p{Surrogate}/u.test(c)) ||\n     (typeof c === 'number' && Number.isFinite(c)));\n}\n// sanitize before build:\ncells = cells.map(c => Number.isFinite(c) ? c : (c == null ? '' : String(c)));","typeGuard":"const isValidCell = (c) =>\n  (typeof c === 'string' && !/\\p{Surrogate}/u.test(c)) ||\n  (typeof c === 'number' && Number.isFinite(c));","tryCatchPattern":"try {\n  buildAgreement(spec);\n} catch (e) {\n  const m = e.message.match(/spec\\.schedule\\[(\\d+)\\]\\[(\\d+)\\]/);\n  if (m) {\n    const [i, j] = [Number(m[1]), Number(m[2])];\n    spec.schedule[i][j] = sanitizeCell(spec.schedule[i][j]);\n    return buildAgreement(spec);\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["validation","unicode","schema","cell-value"],"backgroundTag":"invalid-argument-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"}