santifer/career-ops · warning

⚠️ : ignoring unrecognized header column(s)

Error message

⚠️  ${filename}: ignoring unrecognized header column(s): ${unknown.join(', ')}

What it means

When parseHeadedAddition() finds header labels this version has no meaning for, it does NOT skip the file — it warns and ignores those columns, since unrecognized data can't be stored anyway. The usual cause is a typo'd label, so the warning exists to surface it instead of silently dropping the column's data.

Solutions

  1. Fix the typo'd label to the correct recognized name so the column's data is merged
  2. Remove columns that genuinely carry no tracker meaning
  3. Check the recognized label list in AGENTS.md before inventing new columns

Example fix

// before
num\tdate\tcompnay\trole\t...
// after
num\tdate\tcompany\trole\t...
Defensive patterns

Strategy: validation

Validate before calling

const KNOWN = ['num','date','company','role','score','status','pdf','report','notes','via','location','url'];
const unknown = headerRow.split('\t').filter(l => !KNOWN.includes(l.trim().toLowerCase()));
if (unknown.length) console.error('Typo or unsupported column:', unknown);

Prevention

When it happens

Trigger: A tracker-addition TSV header containing a label outside the recognized set (required: num, date, company, role, score, status, pdf, report; optional: notes, via, location, url) — typically misspellings like 'compnay' or invented fields like 'salary_note'.

Common situations: Typos in hand-written headers; schema drift from a customized local template; fields from another tracker format that career-ops doesn't define.

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 santifer/career-ops@aac998c7ed (2026-09-16). Data as JSON: /api/errors/98443335740ee61f. Report an issue: GitHub.

Appendix: source

Thrown at merge-tracker.mjs:795

 * @param {string[]} lines - Non-empty lines of the addition file.
 * @param {string} filename - Source filename used in warning messages.
 * @returns {object|null} Parsed tracker addition, or null when malformed.
 */
function parseHeadedAddition(lines, filename) {
  const { map, missing, duplicates, unknown } = resolveTsvColumns(splitAdditionCells(lines[0]));
  if (duplicates.length) {
    console.warn(`⚠️  Skipping ${filename}: header labels the same column twice (${[...new Set(duplicates)].join(', ')}) — refusing to guess which one carries the value`);
    return null;
  }
  if (missing.length) {
    console.warn(`⚠️  Skipping ${filename}: header is missing required column(s): ${missing.join(', ')}`);
    return null;
  }
  if (unknown.length) {
    // Not fatal: an unrecognized label is a column this version has no meaning
    // for, and dropping it loses nothing the tracker could store anyway. Say so
    // rather than swallowing it, since the usual cause is a typo'd label.
    console.warn(`⚠️  ${filename}: ignoring unrecognized header column(s): ${unknown.join(', ')}`);
  }

  const dataLines = lines.slice(1);
  if (dataLines.length === 0) {
    console.warn(`⚠️  Skipping ${filename}: header row with no data row`);
    return null;
  }
  if (dataLines.length > 1) {
    // One addition per file is the contract every caller assumes (the merge
    // loop takes one addition per TSV). Rejecting is louder than merging the
    // first row and dropping the rest, which would lose evaluations silently.
    console.warn(`⚠️  Skipping ${filename}: ${dataLines.length} data rows — one addition per file`);
    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 —

View on GitHub (pinned to aac998c7ed)