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
- Fix the typo'd label to the correct recognized name so the column's data is merged
- Remove columns that genuinely carry no tracker meaning
- 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
- Spell header labels exactly as documented in AGENTS.md
- Route custom metadata into the notes column rather than new columns
- Read merge-tracker warnings after each batch — 'ignoring unrecognized column' almost always means a typo
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
- ⚠️ Skipping : header is missing required column(s)
- ⚠️ Skipping : header labels the same column twice ( ) —…
- ⚠️ Non-canonical status
- ⚠️ Skipping : ambiguous extra fields [ ] — expected at most…
- ⚠️ Additions carry a URL but this tracker has no URL…
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)