ErrLookup › Background articles › "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields
"Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields
"Missing required field", "field is required", "X is missing", and "X must be provided" errors fire when a library or API refuses to proceed because a field it treats as mandatory is absent, null, empty, or misnamed. This family holds 105 documented records across 20 repositories, including Chroma's record-set and aggregation validation, LiteLLM batch and logging checks, Nextcloud federation notifications, Rocket.Chat slash commands and integration webhooks, and SiYuan attribute-view templates. The article explains which layer runs the presence check, why libraries refuse to default these fields, how null-versus-absent-versus-empty rules differ per library, and how to fix the payload.
Distilled from 105 documented records across 20 repositories.
Background
These errors are presence checks: a validator looks for a named field in a dict, JSON object, or struct and stops the call when it cannot find a usable value. The check runs at several layers. Client-side validators reject the call before any network traffic - Chroma's TypeScript client throws in prepareRecords when every record-set field is undefined, and LiteLLM's input normalization raises before any HTTP call when an image content block carries no url. Server-side validators answer with request errors, such as Nextcloud's 400 BadRequestException for federation notifications and Rocket.Chat's error-invalid-token for integration updates. Config and schema parsers apply the same rule to files and descriptors (Chroma's operator dicts, Ruflo harness descriptors, ECC's mcpServers check), and internal component contracts apply it to function arguments, as when LiteLLM's logging callbacks expect standard_logging_object in kwargs.
The field is required because the library cannot pick a safe default for it. Chroma has no group-without-aggregate mode and no default k, so an aggregation missing either piece is unexecutable. Rocket.Chat slash commands need a room id because every command callback acts in a room. CodeWhale refuses to persist allow rules without a workspace scope so a grant made in one checkout can never authorize commands in another, and it refuses memory edits without evidence so rewrites of durable context stay auditable. Tailscale will not write credentials lacking the server's Noise public key because that key prevents MITM on first contact. In each case silence would mean guessing at semantics, so the validator fails fast instead.
From the caller's side the messages look uniform - "X is required", "missing X", "X must be provided" - but the details are library-specific. Some validators treat empty strings as missing (Rocket.Chat rejects whitespace-only tokens, Nextcloud rejects empty shareWith or calendarUrl values, Ruflo trims harnessId before testing it), while SiYuan's SSE handler accepts data: null and data: '' and throws only when the data key is absent. Null handling also splits: LiteLLM batch records fail on "input": null or "prompt": null, while AFFiNE's BYOK update demands an explicit description: null to clear the field and throws when the key is merely omitted - and Rocket.Chat's integrations.update does not inherit the stored token at all, so partial updates must resend it.
Two diagnostics recur. First, many messages render the missing name into the text (Nextcloud lists the missing parameter; LiteLLM echoes the record's model; SiYuan wraps the error with the field's key ID), and check order tells you which field survived - Chroma's $min_k parser checks keys before k, so each message maps to exactly one absent field. Second, a few records mean something other than "add the field": LiteLLM's standard_logging_object errors mean the payload builder ran outside litellm's real logging pipeline, LiteLLM batch classification is decided by the url field (so a chat-shaped body labeled /v1/completions fails on missing prompt), and Vector's datadog_events error is a panic in the sink when no message semantic meaning resolves.
Common causes
- Required field omitted from the payload. The field is simply not there: batch JSONL records without input or prompt, collection.modify() calls where every configuration branch produced undefined, message objects built without rid, config dicts missing the key entirely. This is the most common shape across the family.
- Wrong field name or shape. Synonyms and renames are rejected: Chroma accepts exactly 'keys' and 'k' (not key, fields, on, top, count, limit, or n) and 'aggregate' (not 'agg'); ECC requires the mcpServers key spelled exactly; unfilled template placeholders can also drop a key from generated JSON.
- Outer object present, inner payload missing. The container passes but its required member is absent: a SiYuan static template value with type 'text' or 'number' but no text/number object, a litellm image block whose image_url carries no url, a $min_k dict with keys but no k.
- Null where null is rejected - or absent where null is required. Null semantics are library-specific. LiteLLM batch records fail on "input": null or "prompt": null; SiYuan skips value: null as 'leave unset' and accepts data: null; AFFiNE throws when description is absent but accepts an explicit null to clear it. Check which rule applies before serializing.
- Empty or whitespace-only value. Several validators trim first and treat the result as missing: Rocket.Chat rejects whitespace-only integration tokens, Nextcloud rejects empty shareWith/calendarUrl strings, Ruflo rejects whitespace-only harnessId, and CodeWhale rejects evidence that is empty after line-splitting and trimming.
- Payload hand-built instead of using the library's builder. LiteLLM's standard_logging_object errors mean create_datadog_logging_payload or create_llm_obs_payload ran outside the real logging pipeline with fabricated kwargs; Nextcloud custom senders drop notification props; Chroma's validator helpers fire when invoked directly on hand-assembled record sets.
- Partial-update inheritance assumed. Rocket.Chat's integrations.update spreads caller fields verbatim and does not inherit the stored token, so an update that omits it is rejected; AFFiNE requires description to be resent or explicitly nulled. PATCH-like merge semantics cannot be assumed across this family.
- Routing, version, or upstream drift. In LiteLLM batch files the url field wins classification, so a chat-shaped body labeled /v1/completions fails on missing prompt; callback/core version skew can drop standard_logging_object; upstream API changes can omit fields adapters still require, as with Betfair's persistence type.
What usually fixes it
- Send the exact field the message names, with the exact spelling and nesting - synonyms ('key' vs 'keys', 'agg' vs 'aggregate', 'top' vs 'k') are rejected throughout this family; copy the canonical nested body (e.g. Chroma's {'keys': ['#score'], 'k': n}) and edit values only.
- Check the library's null-versus-absent-versus-empty rules before serializing: exclude null keys in LiteLLM batch JSONL, send explicit null to clear AFFiNE's description, use data: '' for SiYuan SSE frames, and never rely on whitespace-only strings passing.
- Assemble payloads with the library's own builders - CalendarFederationNotifier for federation notifications, typed to_dict() constructors for Chroma aggregations, litellm's get_standard_logging_payload helpers, typed request objects for batch files - so required fields cannot drift or be dropped.
- Validate at the boundary before submission: lint batch files against a required-fields schema before upload, run config schema checks in CI, short-circuit empty batches before calling add/update, and re-read the live field schema before saving template values.
- Never assume partial-update inheritance: for endpoints that spread caller fields verbatim, fetch current values first (e.g. Rocket.Chat's integrations.list) and resend them, or use explicit null where the API documents it as the clear operation.
- For internal-contract errors, fix the flow rather than the field: trigger components through the real pipeline, keep package versions consistent (one litellm install, not mixed callback/core versions), and capture real kwargs from hooks instead of fabricating them.
Go deeper
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
- HTTP status errors: handling 4xx and 5xx responses — how to handle 4xx and 5xx responses properly.
Documented occurrences
- At least one of {', '.join(contains_any)} must be provided (chroma-core/chroma)
- Invalid HNSW config provided (chroma-core/chroma)
- Parameters missing in order to complete the request. Missing Parameters: shareWith (nextcloud/server)
- text value is missing (siyuan-note/siyuan)
- You do not have permission to access the requested resource. (chroma-core/chroma)
- OpenMeter: user is required (BerriAI/litellm)
- persistent allow rules must be scoped to a workspace (Hmbown/CodeWhale)
- invalid-command-usage: Executing a command requires at least a message with a room id. (RocketChat/Rocket.Chat)
- error-invalid-token: Invalid token (RocketChat/Rocket.Chat)
- standard_logging_object not found in kwargs (BerriAI/litellm)
- memory edits require non-empty evidence (Hmbown/CodeWhale)
- Batch record for /v1/responses is missing required `input` field: model={openai_request_body.get('model', '')} (BerriAI/litellm)
- The requested resource could not be found: ${input} (chroma-core/chroma)
- Parameters missing in order to complete the request. Missing Parameters: calendarUrl (nextcloud/server)
- description must be provided explicitly. (toeverything/AFFiNE)
- callback_name is required in key_logging (BerriAI/litellm)
- number value is missing (siyuan-note/siyuan)
- event.data is required (siyuan-note/siyuan)
- Batch record for /v1/completions is missing required `prompt` field: model={openai_request_body.get('model', '')} (BerriAI/litellm)
- missing persistence type for order update {} (nautechsystems/nautilus_trader)
…and 85 more across the corpus — use search.
Honest provenance: generated on 2026-08-20 from AI-assisted analysis of the linked records. See how records are made.