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

  1. Set entry: applyAdd({ articleDigest: { dedupKey: 'pp:rag-eval', entry: '- **RAG eval harness** — ...' } }).
  2. Rename the source field to `entry` when constructing the payload (the API accepts only `entry`, not `text`/`point`).
  3. 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

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


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)