{"record":{"id":"c7712a7842b0a76c","repo":"santifer/career-ops","slug":"name-must-not-contain-tabs-or-newlines","errorCode":null,"errorMessage":"--${name} must not contain tabs or newlines","messagePattern":"--(.+?) must not contain tabs or newlines","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"assessment-log.mjs","lineNumber":119,"sourceCode":"      staleFlagged,\n      withoutScore: rows.filter(r => r.score === null).length,\n      withoutThreshold: rows.filter(r => r.threshold === null).length,\n      malformedLines: malformed,\n    },\n  };\n}\n\n// --- Append (`add` subcommand) ---\nexport function buildRow(fields, today) {\n  const req = (name) => {\n    const v = String(fields[name] ?? '').trim();\n    if (!v) throw new Error(`--${name} is required`);\n    if (v.includes('\\t') || v.includes('\\n')) throw new Error(`--${name} must not contain tabs or newlines`);\n    return v;\n  };\n  const opt = (name) => {\n    const v = String(fields[name] ?? '').trim();\n    if (v.includes('\\t') || v.includes('\\n')) throw new Error(`--${name} must not contain tabs or newlines`);\n    return v || '-';\n  };\n  const optPct = (name) => {\n    const v = String(fields[name] ?? '').trim();\n    if (!v) return '-';\n    if (parsePct(v) === null) throw new Error(`--${name} must be a percentage (e.g. 70 or 70%), got \"${v}\"`);\n    return v;\n  };\n  return [\n    today, req('company'), opt('report'), req('platform'), req('subject'),\n    optPct('threshold'), optPct('score'), opt('stale') === '-' ? '' : opt('stale'),\n  ].join('\\t');\n}\n\nfunction addEntry(args) {\n  const fields = {};\n  for (let i = 0; i < args.length; i++) {\n    const m = args[i].match(/^--(company|report|platform|subject|threshold|score|stale)$/);","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/santifer/career-ops/blob/9b17a8ac97b398a496b38e423ae24e433b43254f/assessment-log.mjs#L101-L137","documentation":"Validation in the `req`/`opt` helpers of `buildRow`: no field value may contain a tab (`\\t`) or newline (`\\n`). Because the log is a TSV (tab-separated, one row per line), a stray tab or newline would corrupt the column structure or split a single logical row into many. Both required and optional fields are checked.","triggerScenarios":"Passing `--company 'Acme\\tInc'`, `--subject 'arrays\\nsorting'`, or any value containing literal tab/newline characters; copying multi-line text from a clipboard; programmatically injecting user-typed free text that contains line breaks.","commonSituations":"Pasted values from spreadsheets that embed tabs; multiline notes accidentally routed to a single-line field; agent generating values from a model that emits formatted text with line breaks; CSV-to-TSV conversion preserving embedded newlines.","solutions":["Strip/replace tabs and newlines in each value before invoking: `value.replace(/[\\t\\r\\n]+/g, ' ')`.","Keep assessment-log fields single-line by design — put long-form notes in a different artifact.","Quote/escape at the shell level (`$'...'`) only if you intend spaces, but never feed real tabs.","Validate in your caller: `if (/[\\t\\n]/.test(v)) throw ...`.","Add a test asserting values containing tab/newline are rejected."],"exampleFix":"// before\nfields.company = 'Acme\\tInc'; // throws\n// after\nfields.company = 'Acme\\tInc'.replace(/[\\t\\n]+/g, ' '); // 'Acme Inc'","handlingStrategy":"validation","validationCode":"function sanitizeTsv(v) {\n  const s = String(v ?? '');\n  if (/[\t\n]/.test(s)) throw new Error('Field contains tab or newline');\n  return s.trim();\n}\n// or, to coerce rather than reject:\nconst clean = v.replace(/[\t\r\n]+/g, ' ');","typeGuard":"function isTsvSafe(v) {\n  const s = String(v ?? '');\n  return !/[\t\n]/.test(s);\n}","tryCatchPattern":null,"preventionTips":["Strip tabs/newlines from any pasted or model-generated value before invoking.","Keep assessment-log fields single-line by design.","Sanitize at the input boundary, not at TSV-write time.","Test that embedded tabs/newlines are rejected."],"tags":["validation","tsv","cli","assessment-log","sanitization"],"backgroundTag":null,"analyzedSha":"9b17a8ac97b398a496b38e423ae24e433b43254f","analyzedAt":"2026-08-13T00:48:39.135Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}