santifer/career-ops · error · Error
-- must not contain tabs or newlines
Error message
--${name} must not contain tabs or newlines What it means
In buildRow(), req() validates required fields and rejects any value containing a tab or newline character. assessments.tsv is a tab-delimited append-only file, so an embedded \t or \n would shift or break the row's column structure. The library fails fast rather than writing a corrupt row.
Solutions
- Remove tabs/newlines from the offending value and re-run the command (replace with a space).
- Sanitize with tr: `--subject "$(echo "$SUBJECT" | tr '\t\n' ' ')"`.
- If calling buildRow() programmatically, pre-clean the value: v.replace(/[\t\n]/g, ' ').trim().
- Use a shell single-line string and verify with `echo "$VALUE" | cat -A` if unsure where the invisible character is.
Example fix
// before
buildRow({ company: "Acme\nHoldings", platform: "codesignal", subject: "algo" }, today)
// Error: --company must not contain tabs or newlines
// after
buildRow({ company: "Acme Holdings", platform: "codesignal", subject: "algo" }, today) Defensive patterns
Strategy: validation
Validate before calling
function isTsvSafe(v) { return !/[\t\n]/.test(String(v).trim()); }
// check all values before calling buildRow
if (!Object.values(fields).every(isTsvSafe)) throw new Error('values must not contain tabs or newlines'); Type guard
const isTsvSafe = (v) => typeof v === 'string' && !/[\t\n]/.test(v.trim());
Try / catch
try {
const row = buildRow(fields, today);
} catch (err) {
if (err.message.includes('must not contain tabs or newlines')) {
const flag = err.message.split(' ')[0].replace('--', '');
fields[flag] = String(fields[flag]).replace(/[\t\n]/g, ' ').trim();
return buildRow(fields, today); // retry with sanitized value
}
throw err;
} Prevention
- Pipe pasted values through `tr '\t\n' ' '` before use.
- Avoid `$(cat file)` substitution for flag values; read single-line values only.
- Inspect suspicious values with `cat -A` to reveal hidden tabs/newlines.
- Sanitize input centrally if you drive `add` from a script.
When it happens
Trigger: Calling buildRow() with a required field (company, platform, subject) whose trimmed value contains '\t' or '\n' — e.g. pasting a multi-line company name, a subject copied from a PDF with a line break, or an argument that literally contains tab characters.
Common situations: Copying a course or platform name from a website/Slack that carries a trailing newline; shell command substitution `--subject "$(cat notes.txt)"` pulling in line breaks; editors inserting tabs; programmatic callers passing unsanitized user input.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Application Answers section has
- --from and --to must both be supplied together (or neither…
- --from ( ) must not be after --to ( ).
- Invalid page budget " ". Use a positive integer.
- --limit must be an integer from 1 to 100
AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16).
Data as JSON: /api/errors/c7712a7842b0a76c.
Report an issue: GitHub.
Appendix: source
Thrown at assessment-log.mjs:127
return {
assessments: rows,
aggregates: { byPlatform },
quality: {
total: rows.length,
staleFlagged,
withoutScore: rows.filter(r => r.score === null).length,
withoutThreshold: rows.filter(r => r.threshold === null).length,
malformedLines: malformed,
},
};
}
// --- Append (`add` subcommand) ---
export function buildRow(fields, today) {
const req = (name) => {
const v = String(fields[name] ?? '').trim();
if (!v) throw new Error(`--${name} is required`);
if (v.includes('\t') || v.includes('\n')) throw new Error(`--${name} must not contain tabs or newlines`);
return v;
};
const opt = (name) => {
const v = String(fields[name] ?? '').trim();
if (v.includes('\t') || v.includes('\n')) throw new Error(`--${name} must not contain tabs or newlines`);
return v || '-';
};
const optPct = (name) => {
const v = String(fields[name] ?? '').trim();
if (!v) return '-';
if (parsePct(v) === null) throw new Error(`--${name} must be a percentage (e.g. 70 or 70%), got "${v}"`);
return v;
};
return [
today, req('company'), opt('report'), req('platform'), req('subject'),
optPct('threshold'), optPct('score'), opt('stale') === '-' ? '' : opt('stale'),
].join('\t');
}View on GitHub (pinned to aac998c7ed)