santifer/career-ops · error · Error
Application answer state must be one of
Error message
Application answer state must be one of: ${[...VALID_STATES].join(', ')} What it means
application-answers.mjs validates the application answer state against the fixed set VALID_STATES = {'filled','submitted'}. normalizeState lowercases the input and throws when it is not a member, listing the allowed values in the message. This keeps the application-answers snapshot file limited to canonical states.
Solutions
- Change the state string to a canonical value: 'filled' or 'submitted' (case-insensitive; input is lowercased).
- Map foreign state names to canonical ones at the boundary before saving, e.g. draft -> filled, done/sent -> submitted.
- Print VALID_STATES or read the error message to see the exact allowed set before retrying.
Example fix
// before
saveAnswers({ state: 'draft', answers });
// after
const ALIASES = { draft: 'filled', done: 'submitted', sent: 'submitted' };
const state = ALIASES[rawState] ?? rawState;
saveAnswers({ state, answers }); Defensive patterns
Strategy: validation
Validate before calling
const VALID_STATES = new Set(['filled', 'submitted']);
if (!VALID_STATES.has(String(state || 'filled').toLowerCase())) {
throw new Error(`state must be filled or submitted, got: ${state}`);
} Type guard
function isCanonicalAnswerState(v) {
return typeof v === 'string' && ['filled', 'submitted'].includes(v.toLowerCase());
} Try / catch
try {
saveAnswers({ state, answers });
} catch (err) {
if (String(err.message).startsWith('Application answer state must be one of')) {
console.error(`Invalid state "${state}"; use filled or submitted`);
process.exitCode = 2;
return;
}
throw err;
} Prevention
- Keep a single ALIASES map converting any foreign state names ('draft', 'done') to canonical values at every boundary.
- Lowercase and trim state strings before passing them into library calls.
- Add a lint/test asserting every state literal in your codebase is in {filled, submitted}.
When it happens
Trigger: Calling normalizeState or any API that routes state through it (write/save of an application answer record) with state values like 'draft', 'complete', 'FILLED ' that isn't in the set, an empty string, or a boolean/number instead of a string.
Common situations: Migrating from another tool whose states were 'draft'/'done'; typo-ing 'submited'; wiring a UI dropdown that emits different labels; hand-editing the JSON state file with a non-canonical state.
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
- decision must be one of
- invalid format " " (use: )
- payload.articleDigest requires a non-empty dedupKey (used…
- --sort must be date or score
- torre: invalid experience
AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16).
Data as JSON: /api/errors/b9fd59f95fc44b9c.
Report an issue: GitHub.
Appendix: source
Thrown at application-answers.mjs:39
for (const key of keys) {
const value = object?.[key];
if (Array.isArray(value)) {
if (value.length > 0) return value;
continue;
}
if (value !== undefined && value !== null && String(value).trim()) return value;
}
return '';
}
function list(value) {
return Array.isArray(value) ? value : [];
}
function normalizeState(state) {
const normalized = inline(state || 'filled').toLowerCase();
if (!VALID_STATES.has(normalized)) {
throw new Error(`Application answer state must be one of: ${[...VALID_STATES].join(', ')}`);
}
return normalized;
}
function normalizeDate(date) {
return inline(date || new Date().toISOString().slice(0, 10));
}
function quoteBlock(value) {
const text = String(value ?? '').replace(/\r\n/g, '\n').trim();
if (!text) return '> Not recorded.';
return text.split('\n').map((line) => `> ${line}`).join('\n');
}
function qaLines(entries, { labelKeys, valueKeys, fallback }) {
if (entries.length === 0) return ['- None captured.'];
return entries.flatMap((entry, index) => {View on GitHub (pinned to aac998c7ed)