santifer/career-ops · error · Error
payload.articleDigest requires
Error message
payload.articleDigest requires { entry } What it means
When payload.articleDigest is present, applyAdd requires an `entry` — the proof-point markdown to insert into article-digest.md. Unlike the cv branch, dedupKey is validated separately and article-digest.md is auto-created from a default header when missing; but without an entry there is nothing to insert, so the call is rejected.
Solutions
- Set entry: applyAdd({ articleDigest: { dedupKey: 'pp:rag-eval', entry: '- **RAG eval harness** — ...' } }).
- Rename the source field to `entry` when constructing the payload (the API accepts only `entry`, not `text`/`point`).
- If the goal was dedup-checking an existing entry, read article-digest.md and use articleDigestHasEntry directly instead of applyAdd.
Example fix
// before
await applyAdd({ articleDigest: { dedupKey: point.slug, text: point.body } }, { articleText });
// after
await applyAdd(
{ articleDigest: { dedupKey: point.slug, entry: point.body } },
{ articleText }
); Defensive patterns
Strategy: validation
Validate before calling
function isValidDigestPayload(ad) {
return Boolean(ad && ad.entry);
}
if (payload.articleDigest && !isValidDigestPayload(payload.articleDigest)) throw new Error('articleDigest payload needs { entry }'); Type guard
function isDigestTarget(ad) {
return typeof ad === 'object' && ad !== null && typeof ad.entry === 'string' && ad.entry.length > 0;
} Try / catch
try {
applyAdd({ articleDigest: digestTarget }, { articleText });
} catch (e) {
if (e.message.includes('payload.articleDigest requires')) {
console.error('articleDigest payload must carry the proof-point text as `entry`');
} else throw e;
} Prevention
- Map source fields (text/point/body) to `entry` explicitly in the payload builder.
- Share one typed factory for cv and articleDigest payloads so both always carry `entry`.
- Add a test asserting applyAdd({ articleDigest: { dedupKey: 'x' } }) throws, locking the contract in.
When it happens
Trigger: applyAdd({ articleDigest: {} }), applyAdd({ articleDigest: { dedupKey: 'x' } }) (dedupKey but no entry), or applyAdd({ articleDigest: { entry: '' } }) — a truthy articleDigest object with a falsy entry.
Common situations: Building both payload branches from one template and the articleDigest branch never receiving its entry field, destructuring a record where the proof-point text lives under a different property name (e.g. `text` or `point` instead of `entry`), or passing only dedupKey intending to reference an existing entry.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- payload.cv requires
- apify: entry has invalid field_map. Each of title, url…
- Existing candidates file at
- Gemini returned an invalid career-ops report
- invalid golden case : need string id/jd and label.
AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16).
Data as JSON: /api/errors/01c9193230dad3ac.
Report an issue: GitHub.
Appendix: source
Thrown at add-entry.mjs:195
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 aac998c7ed)