{"record":{"id":"ba34e3cf4b22fadd","repo":"santifer/career-ops","slug":"skipping-malformed-tsv-filename-parts-le","errorCode":null,"errorMessage":"⚠️  Skipping malformed TSV ${filename}: ${parts.length} fields","messagePattern":"⚠️  Skipping malformed TSV (.+?): (.+?) fields","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"merge-tracker.mjs","lineNumber":690,"sourceCode":"      date: parts[1],\n      company: parts[2],\n      role: parts[3],\n      // Write-canonical: the tracker stores scores unbolded (verify-pipeline\n      // rejects bold scores), so strip any markdown bold from the incoming cell.\n      score: resolved.score.replace(/\\*\\*/g, '').trim(),\n      status: validateStatus(resolved.status),\n      pdf: parts[6],\n      report: parts[7],\n      notes: parts[8] || '',\n    };\n    const extras = parseTsvExtras(parts, filename);\n    if (!extras) return null;\n    Object.assign(addition, extras);\n  } else {\n    // Tab-separated\n    parts = content.split('\\t');\n    if (parts.length < 8) {\n      console.warn(`⚠️  Skipping malformed TSV ${filename}: ${parts.length} fields`);\n      return null;\n    }\n\n    // Column order varies: batch TSVs write (status, score), applications.md is\n    // (score, status). Identify each by content — the score cell is recognizable\n    // by pattern, a status never is — so a reordered TSV merges correctly and an\n    // undecidable row is skipped loudly instead of merging swapped data (#1427).\n    const resolved = resolveScoreStatus(parts[4].trim(), parts[5].trim());\n    if (!resolved) {\n      console.warn(`⚠️  Skipping ${filename}: cannot tell score from status in columns 5–6 (\"${parts[4].trim()}\" | \"${parts[5].trim()}\") — refusing to merge a possible column swap`);\n      return null;\n    }\n\n    addition = {\n      num: parseInt(parts[0]),\n      date: parts[1],\n      company: parts[2],\n      role: parts[3],","sourceCodeStart":672,"sourceCodeEnd":708,"githubUrl":"https://github.com/santifer/career-ops/blob/60398d6549a46f5266929538af21cfab94badc75/merge-tracker.mjs#L672-L708","documentation":"For tab-separated additions, merge-tracker.mjs splits the line on tabs and requires at least 8 fields (9 columns is the documented format; notes is field 9 and extras follow). Fewer than 8 means a required column is missing, so the file is skipped with this warning instead of merging misaligned data.","triggerScenarios":"A TSV line with 7 or fewer tab-separated cells — e.g. notes omitted AND an earlier column missing — makes parts.length < 8 and the addition is rejected before any content-based resolution runs.","commonSituations":"Hand-writing the TSV and dropping the pdf or report column; a CSV file (comma-separated) fed in where only 1 'field' is found after tab-splitting; line-editor that collapsed tabs.","solutions":["Rewrite the line with the full 9 tab-separated columns: num, date, company, role, status, score, pdf, report, notes","Verify the file is tab-delimited, not comma-delimited","Regenerate the TSV from the documented template and re-run node merge-tracker.mjs"],"exampleFix":"# before (7 fields)\n042\t2026-08-20\tAcme\tSRE\tInterview\t4.2/5\t[042](reports/042-acme-2026-08-20.md)\n\n# after (9 fields)\n042\t2026-08-20\tAcme\tSRE\tInterview\t4.2/5\t✅\t[042](reports/042-acme-2026-08-20.md)\tnote","handlingStrategy":"validation","validationCode":"function tsvRowHasAllColumns(line) {\n  return line.split('\\t').length >= 8;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Write additions with a script that emits the 9 tab-separated columns","Confirm the file is tab-delimited (comma-separated files fail this check)"],"tags":["tracker","tsv-parsing","merge","column-count","warning"],"backgroundTag":"column-count-mismatch","analyzedSha":"60398d6549a46f5266929538af21cfab94badc75","analyzedAt":"2026-08-20T23:00:06.764Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}