santifer/career-ops · warning
⚠️ Non-canonical status
Error message
⚠️ Non-canonical status "${status}" → defaulting to "Evaluated" What it means
merge-tracker.mjs's validateStatus() normalizes TSV status values to canonical states (see templates/states.yml): it checks an alias table, special-cases DUPLICADO/repost → Discarded, and for anything unrecognized warns and defaults to 'Evaluated'. An unrecognized status silently reshapes the row's lifecycle state in the tracker.
Solutions
- Replace the status value in the TSV with a canonical state from templates/states.yml (Evaluated, Applied, Responded, Interview, Offer, Hired, Rejected, Discarded, SKIP)
- Use set-status.mjs afterwards to move the row to the correct state via the canonical write path
- If the value is a recurring localized synonym, it may merit an alias entry rather than per-row fixes
- Run node normalize-statuses.mjs to sweep existing non-canonical statuses in the tracker
Example fix
// before cat 2026-09-16 Acme Engineer Evaluated? 4.2/5 ✅ [42](reports/042-...) // after cat 2026-09-16 Acme Engineer Evaluated 4.2/5 ✅ [42](reports/042-...)
Defensive patterns
Strategy: validation
Validate before calling
const CANONICAL = ['Evaluated','Applied','Responded','Interview','Offer','Hired','Rejected','Discarded','SKIP'];
if (!CANONICAL.includes(status)) throw new Error('Non-canonical status: ' + status); Prevention
- Copy status values only from templates/states.yml when writing TSV rows
- Never put markdown bold or dates in the status field
- Use set-status.mjs for status changes instead of hand-editing
- Run normalize-statuses.mjs periodically to catch drift
When it happens
Trigger: A tracker-addition TSV in batch/tracker-additions/ (or legacy row) whose status column holds a value that matches neither a canonical state nor an alias — e.g. 'sent last week', 'in progress', a localized non-aliased word, or a status with markdown bold.
Common situations: Hand-written TSV rows, imports from another tracker with different state names, typos like 'Evaluted' or lowercase variants missing from the alias table.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Cross-channel duplicate
- # : company " " looks like a confidentiality placeholder —…
- ⚠️ : ignoring unrecognized header column(s)
- INVALID_DATE
- ⚠️ Skipping : ambiguous extra fields [ ] — expected at most…
AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16).
Data as JSON: /api/errors/19e5c1737fd669cc.
Report an issue: GitHub.
Appendix: source
Thrown at merge-tracker.mjs:206
// Spanish → English
'evaluada': 'Evaluated', 'condicional': 'Evaluated', 'hold': 'Evaluated', 'evaluar': 'Evaluated', 'verificar': 'Evaluated',
'aplicado': 'Applied', 'enviada': 'Applied', 'aplicada': 'Applied', 'applied': 'Applied', 'sent': 'Applied',
'respondido': 'Responded',
'entrevista': 'Interview',
'oferta': 'Offer',
'rechazado': 'Rejected', 'rechazada': 'Rejected',
'contratado': 'Hired', 'contratada': 'Hired', 'accepted': 'Hired', 'accept': 'Hired',
'descartado': 'Discarded', 'descartada': 'Discarded', 'cerrada': 'Discarded', 'cancelada': 'Discarded',
'no aplicar': 'SKIP', 'no_aplicar': 'SKIP', 'skip': 'SKIP', 'monitor': 'SKIP',
'geo blocker': 'SKIP',
};
if (aliases[lower]) return aliases[lower];
// DUPLICADO/Repost → Discarded
if (/^(duplicado|dup|repost)/i.test(lower)) return 'Discarded';
console.warn(`⚠️ Non-canonical status "${status}" → defaulting to "Evaluated"`);
return 'Evaluated';
}
// normalizeVia (Unicode-aware Via/agency key, #1596/#1603) lives in
// tracker-parse.mjs so merge-tracker and analyze-patterns share ONE normalizer
// and agency identity can't drift between scripts. (normalizeCompany lives in
// tracker-utils.mjs since #1460 so every tracker writer shares one company key.)
/**
* Extract the bracketed report number from a Markdown report link.
*
* Report-number equality is an exact duplicate signal, but only after company
* equality is confirmed by the caller. This helper reads links such as
* `[123](../reports/123-company-role-date.md)` and returns the numeric id.
*
* Layouts whose header has no dedicated Report column (e.g. a customized
* `… | Materials | Apply Link | Follow-up | Notes` shape) embed the link in
* Notes prose instead (see buildRow), so the Notes cell is scanned as aView on GitHub (pinned to aac998c7ed)