santifer/career-ops · warning

⚠️ Skipping : data row has field(s), missing the required…

Error message

⚠️  Skipping ${filename}: data row has ${parts.length} field(s), missing the required cell(s): ${missingRequiredCells.join(', ')}

What it means

In a headed TSV, every required field (num, date, company, role, score, status, pdf, report) must have a cell present in the data row. If the row is shorter than a required label's column index, the parser cannot map the row onto the header and skips the file. Optional trailing cells may be absent (absent and empty read the same), but a short row that cuts off a REQUIRED cell is rejected; an interior omission that shifts values is caught separately by the score corroboration.

Solutions

  1. Count the tab-separated cells in the data row against the header labels and append the missing required cell(s) named in the warning, in header order.
  2. Use the documented sentinels where a value genuinely doesn't exist: '—' or 'N/A' for score, '—' for report, '❌' for pdf.
  3. Ensure the file is tab-delimited, not comma- or space-delimited; re-save with real tabs if an editor converted them.
  4. Fix the emitter template so it always writes one tab per header label, even when a value is empty.

Example fix

// before (row stops after role — score/status/pdf/report missing)
num	date	company	role	score	status	pdf	report
42	2026-09-16	Acme	Backend Engineer

// after
num	date	company	role	score	status	pdf	report
42	2026-09-16	Acme	Backend Engineer	4.2/5	Evaluated	❌	[042](reports/042.md)
Defensive patterns

Strategy: validation

Validate before calling

const REQUIRED = ['num','date','company','role','score','status','pdf','report'];
const header = lines[0].split('\t');
const cells = lines[1].split('\t');
const missing = REQUIRED.filter(label => header.indexOf(label) >= cells.length);
if (missing.length) throw new Error(`${file}: data row missing required cell(s): ${missing.join(', ')}`);

Prevention

When it happens

Trigger: parseHeadedAddition (merge-tracker.mjs:825) computes shortLabels = labels whose column index >= parts.length, filters to TSV_REQUIRED_FIELDS, and finds a non-empty set — i.e. splitAdditionCells(dataLines[0]) produced fewer tab-separated cells than the position of some required label.

Common situations: A writer emitted only 4-7 of the 8 required cells, stopping after notes; a template's header was edited to add a column but the data row wasn't updated; a shell script built the row with a failing variable leaving the tail empty; tabs were converted to spaces by an editor, collapsing cells.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16). Data as JSON: /api/errors/68799f488687d703. Report an issue: GitHub.

Appendix: source

Thrown at merge-tracker.mjs:826

    return null;
  }

  const parts = splitAdditionCells(dataLines[0]);
  // Only the REQUIRED cells must actually be there. A row whose trailing
  // optional value is empty is routinely written without its final tab —
  // openrouter-runner emits `…\treport\t\n` for an absent note, and an LLM
  // writer asked for "leave the last field empty" often just stops — so
  // demanding a cell for every label would reject canonical rows. Absent and
  // empty read the same here, which is what the batch and web prompts already
  // promise their writers.
  //
  // This is not the defense against a SHIFTED row: an omitted interior cell
  // slides every later value one column left, which the score corroboration
  // below catches by content regardless of the row's width.
  const shortLabels = Object.entries(map).filter(([, i]) => i >= parts.length).map(([k]) => k);
  const missingRequiredCells = shortLabels.filter(k => TSV_REQUIRED_FIELDS.includes(k));
  if (missingRequiredCells.length) {
    console.warn(`⚠️  Skipping ${filename}: data row has ${parts.length} field(s), missing the required cell(s): ${missingRequiredCells.join(', ')}`);
    return null;
  }

  const at = (k) => (map[k] != null ? String(parts[map[k]] ?? '').trim() : '');
  const optional = (k) => {
    const v = at(k);
    return PLACEHOLDER_CELL.test(v) ? '' : v;
  };

  // A required cell that is PRESENT but blank is a writer that did not supply
  // the value, and blank is never the way to say "none" here: every required
  // field has a documented value, and the "no data" cases have sentinels
  // (`—` / `N/A` for score, `—` for report, `❌` for pdf). Left unchecked, an
  // empty status reaches validateStatus(''), which warns and returns
  // "Evaluated" — recording a real evaluation state the row never claimed.
  const blankRequiredCells = TSV_REQUIRED_FIELDS.filter(k => at(k) === '');
  if (blankRequiredCells.length) {
    console.warn(`⚠️  Skipping ${filename}: required cell(s) present but empty: ${blankRequiredCells.join(', ')} — use the documented sentinel (— / N/A) rather than a blank cell`);

View on GitHub (pinned to aac998c7ed)