santifer/career-ops · error · Error
payload.articleDigest requires { entry }
Error message
payload.articleDigest requires { entry } What it means
Per-target validation in `applyAdd` for the `articleDigest` payload: when present, it must include a non-empty `entry` (the proof-point text to append). Unlike the cv branch, `dedupKey` is checked by a separate guard immediately after, but the entry itself is the first mandatory field because there's nothing to append without it.
Source
Thrown at add-entry.mjs:171
if (payload.cv) {
const { section, dedupKey, entry } = payload.cv;
if (!section || !entry) throw new Error('payload.cv requires { section, entry }');
// dedupKey is what makes the insert idempotent — refuse to add without one
// rather than silently allowing duplicate re-runs.
if (!normalizeKey(dedupKey)) throw new Error('payload.cv requires a non-empty dedupKey (used for dedup/idempotency)');
if (cvText === null) throw new Error(`cv.md not found — cannot add to a CV that does not exist`);
if (cvHasEntry(cvText, section, dedupKey)) {
result.cv = { status: 'duplicate', section };
} else {
cv = insertIntoCvSection(cvText, section, entry);
result.cv = { status: 'added', section };
}
}
if (payload.articleDigest) {
const { dedupKey, entry } = payload.articleDigest;
if (!entry) throw new Error('payload.articleDigest requires { entry }');
if (!normalizeKey(dedupKey)) throw new Error('payload.articleDigest requires a non-empty dedupKey (used for dedup/idempotency)');
// article-digest.md is optional; create it from a header when missing.
const current = articleText === null
? '# Article Digest -- Proof Points\n\nCompact proof points from portfolio projects. Read by career-ops at evaluation time.\n'
: articleText;
if (articleDigestHasEntry(current, dedupKey)) {
result.articleDigest = { status: 'duplicate' };
articleDigest = articleText;
} else {
articleDigest = appendArticleDigest(current, entry);
result.articleDigest = { status: articleText === null ? 'created' : 'added' };
}
}
return { cv, articleDigest, result };
}
async function readStdin() {View on GitHub (pinned to 9b17a8ac97)
Solutions
- Include a non-empty `entry` string in `payload.articleDigest` (the actual proof-point line to append).
- Use the exact key names `{ dedupKey, entry }` — do not substitute `text`/`body`/`content`.
- Generate the entry eagerly upstream; if generation fails, do not call applyAdd at all.
- Add a caller-side guard: `if (p.articleDigest && !p.articleDigest.entry) throw ...`.
- Cover both missing-entry and missing-dedupKey paths in tests.
Example fix
// before
applyAdd({ articleDigest: { dedupKey: 'kpi-x' } }); // throws — no entry
// after
applyAdd({
articleDigest: {
dedupKey: 'kpi-x',
entry: '- KPI X: cut p95 latency 40% via caching (2024)'
}
}); Defensive patterns
Strategy: validation
Validate before calling
function validateDigestPayload(d) {
return !!d && typeof d === 'object' &&
typeof d.entry === 'string' && d.entry.trim() !== '';
}
if (payload.articleDigest && !validateDigestPayload(payload.articleDigest)) {
throw new Error('payload.articleDigest needs non-empty { entry }');
} Type guard
function isDigestEntry(d) {
return !!d && typeof d === 'object' &&
typeof d.entry === 'string' && d.entry.trim() !== '';
} Prevention
- Use the exact key `entry` (not text/body/content).
- Generate proof-point text eagerly; skip the call if generation returns empty.
- Always pair entry with a dedupKey (checked by the next guard).
- Cover both missing-entry and missing-dedupKey in tests.
When it happens
Trigger: Calling `applyAdd({ articleDigest: { dedupKey: 'x' } })` (no entry); `applyAdd({ articleDigest: {} })`; `applyAdd({ articleDigest: { entry: '' } })`. Any truthy `payload.articleDigest` object without a non-empty `entry`.
Common situations: Caller wires up the digest dedupKey but forgets to attach the generated proof-point text; entry is built from a template that returned empty; agent passes the metadata shape but not the content; misreading the schema and putting the text under a different key (e.g. `text`, `body`).
Related errors
- payload must include at least one of: cv, articleDigest
- payload.cv requires { section, entry }
- payload.cv requires a non-empty dedupKey (used for dedup/ide
- Application answer state must be one of: ${[...VALID_STATES]
- Missing value for ${arg}
AI-assisted analysis of santifer/career-ops@9b17a8ac97 (2026-08-13).
Data as JSON: /api/errors/01c9193230dad3ac.
Report an issue: GitHub.