santifer/career-ops · error
changedSections must be an array
Error message
changedSections must be an array
What it means
Thrown by writeReuseDecision() when changedSections is not an Array. The field records which CV sections changed (serialized as changed_sections in the JSON record); a bare Array.isArray check guards it because strings are the common accidental shape.
Source
Thrown at application-artifacts.mjs:87
join(paths.root, 'cv', 'source'),
paths.cv.tailored.root,
join(paths.root, 'decision'),
]) mkdirSync(directory, { recursive: true });
return paths;
}
/** Write an auditable CV reuse decision beside the application artifacts. */
export function writeReuseDecision(paths, {
decision,
score = null,
sourceCv = null,
currentJd = null,
previousSource = null,
changedSections = [],
userOverride = false,
}) {
if (!DECISIONS.has(decision)) throw new Error(`decision must be one of: ${[...DECISIONS].join(', ')}`);
if (!Array.isArray(changedSections)) throw new Error('changedSections must be an array');
ensureApplicationArtifactDirs(paths);
const record = {
schema_version: 1,
decision,
score,
source_cv: sourceCv,
current_jd: currentJd,
previous_source: previousSource,
changed_sections: changedSections,
user_override: Boolean(userOverride),
recorded_at: new Date().toISOString(),
};
writeFileSync(paths.decision.reuse, `${JSON.stringify(record, null, 2)}\n`);
return record;
}
function usage() {
return 'Usage: node application-artifacts.mjs --report N --company NAME --role ROLE [--version N] [--root output] [--init]';View on GitHub (pinned to 60398d6549)
Solutions
- Pass a real array: changedSections: ['summary', 'skills']
- If the value arrives as a string, split it first: typeof s === 'string' ? s.split(',').map(x => x.trim()).filter(Boolean) : s
- When nothing changed, omit the field entirely — the default [] is valid
Example fix
// before
writeReuseDecision(paths, { decision: 'reuse', changedSections: 'summary, skills' });
// after
writeReuseDecision(paths, { decision: 'reuse', changedSections: ['summary', 'skills'] }); Defensive patterns
Strategy: type-guard
Validate before calling
if (changedSections !== undefined && !Array.isArray(changedSections)) {
throw new TypeError('changedSections must be an array of section names');
} Type guard
function isSectionList(v) {
return v === undefined || (Array.isArray(v) && v.every((s) => typeof s === 'string'));
} Prevention
- Never reuse a ', '-joined string that was built for logging as the changedSections value
- Omit the field when nothing changed — the [] default is valid
When it happens
Trigger: changedSections: 'summary, skills' (comma-separated string), changedSections: 'summary', or an object keyed by section name. The parameter defaults to [] so the throw always comes from an explicitly passed non-array.
Common situations: Passing a human-readable list as one string; a caller upstream joining an array with ', ' for logging and reusing the joined value; config-driven call sites reading the field from YAML/JSON that holds a string.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- reportNum must be a numeric report number
- version must be a positive integer
- decision must be one of: ${[...DECISIONS].join(', ')}
- --limit must be an integer from 1 to 100
- --months must be an integer from 1 to 120
AI-assisted analysis of santifer/career-ops@60398d6549 (2026-08-20).
Data as JSON: /api/errors/598a07e5b0c7d82f.
Report an issue: GitHub.