affaan-m/ECC · error · Error

spec.schedule must be an array of six-cell rows

Error message

spec.schedule must be an array of six-cell rows

What it means

renderScheduleRows renders spec.schedule into a markdown table row set. If spec.schedule is present but not an array, the builder rejects it immediately. The library distinguishes 'undefined' (renders a default empty schedule row) from a wrongly-typed value, which is treated as a specification error.

Solutions

  1. Change spec.schedule to an array of rows, each row itself an array of exactly six cells.
  2. If the intent is no schedule, omit the field entirely (undefined) rather than passing a wrong type.
  3. Validate the spec with Array.isArray(spec.schedule) before building.
  4. Check the spec file's syntax: a missing dash/bracket in YAML can turn an array into a scalar or mapping.

Example fix

// before
const spec = { schedule: { monday: ['09:00', ...] } };
// after
const spec = { schedule: [['monday', '09:00', '17:00', 'break', '60', 'note']] }; // array of six-cell rows
Defensive patterns

Strategy: validation

Validate before calling

function assertScheduleArray(spec) {
  if (spec.schedule !== undefined && !Array.isArray(spec.schedule)) {
    throw new TypeError('spec.schedule must be an array of six-cell rows (or omitted)');
  }
}

Type guard

const isSchedule = (s) => s === undefined || (Array.isArray(s) && s.every(Array.isArray));

Try / catch

try {
  buildAgreement(spec);
} catch (e) {
  if (e.message.includes('spec.schedule must be an array')) {
    spec = { ...spec, schedule: normalizeSchedule(spec.schedule) };
    return buildAgreement(spec);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling buildValues/build-agreement with a spec where schedule is a non-array value — e.g. a string 'monday', an object { rows: [...] }, a Map, or JSON where schedule was meant to be an array of arrays.

Common situations: Hand-written YAML/JSON spec where the schedule was written as an object or string; a loader that collapsed the array; copy-pasting a single row (object) instead of an array of rows; schema drift after editing the spec generator.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/148adf941e3b69a2. Report an issue: GitHub.

Appendix: source

Thrown at skills/master-agreement-generator/scripts/build-agreement.js:60

  return now.toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' });
}

function encodeScheduleCell(cell) {
  const entity = character => `&#${character.codePointAt(0)};`;
  // Entities keep data out of Markdown/HTML syntax, including smart punctuation.
  // Preserve single internal spaces and ordinary dates/example text as written.
  return String(cell).replace(/\r\n|\r|\n/g, ' ')
    .replace(/[\\|`*_{}[\]<>!&#~^$'"@]/g, entity)
    .replace(/-{2,}|\.{3,}/g, run => [...run].map(entity).join(''))
    .replace(/^ +| +$| {2,}|[^\S ]/gu, run => [...run].map(entity).join(''));
}

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');
}

View on GitHub (pinned to 8321021c54)