Skip to content
JSON2026-08-286 min read

JSON Schema Reports "required" Property Missing — How to Locate and Fix

Symptom: validation fails, error points at required

You validate some JSON and the Schema returns something like:

{
  "keyword": "required",
  "message": "should have required property 'email'",
  "missingProperty": "email"
}

It means: the Schema requires an email field, but your data doesn't have it. Sounds simple, but "I clearly wrote it yet it's still missing" is common — the root cause is often nesting, $ref, or a oneOf that hides the real message.

Why "written but still missing"

1. Field name typo / case mismatch

The Schema wants email; your data has Email or e-mail — JSON field names are case-sensitive, one character off counts as missing. Data coming from Excel or another language's serializer is a frequent source (Go json:"eMail" tags, Python snake_case). Diffing the live payload against a known-good sample with JSON Diff surfaces the mismatched keys faster than scanning long field lists by eye.

2. Wrong nesting level

required applies to the object at its own level. For example:

{
  "type": "object",
  "properties": {
    "user": {
      "type": "object",
      "required": ["email"],
      "properties": { "email": { "type": "string" } }
    }
  }
}

Here required: ["email"] only constrains the user sub-object, not the top level. If your email is at the top level, it reports missing. Read the error path (for example /user) before searching the whole file for the field name.

3. Forgot to wrap array items

Each element of an array must satisfy the Schema in items. A common mistake is putting required on the array itself instead of on the object inside items:

{
  "type": "array",
  "items": {
    "type": "object",
    "required": ["id"]
  }
}

Error paths usually include an index (such as /2), which is far more useful than a generic "array validation failed".

The additionalProperties trap

If you set "additionalProperties": false, then any field not declared in the Schema also errors (not just missing — extra fields too). During debugging, set it to true or comment it out first, then tighten later.

Another frequent mix-up: putting required inside properties does nothing — it must be a sibling keyword next to properties. Validators often stay silent about that mistake; the rule simply never fires, and teams conclude "required is broken".

required fails inside oneOf: the silent majority

When required sits inside a oneOf branch, the error message often does not say "required" at all — modern validators report "must match exactly one schema in oneOf" while the root cause is one branch's required field missing. The diagnosis trick: validate against each oneOf branch separately (temporarily lift them to the top level); the branch whose error list suddenly becomes readable is your culprit. anyOf is kinder — first-match-wins — so a schema that migrated from oneOf to anyOf to "make errors go away" has usually just disabled the exclusivity the design intended. Keep oneOf, add a discriminating field ("type": "payment_card" vs "type": "bank_account"), and fix the data.

required plus $ref: where the field actually went

A schema that $refs a shared definition inherits that definition's required array verbatim — you cannot easily override required per-use-site in draft-07 (2020-12 gains some relief via unevaluatedProperties patterns). If two endpoints reuse a $defs/user but need different mandatory fields, split the definition or wrap with allOf and add endpoint-specific required at the outer level. The error location may point into the referenced file while your editor shows the referencing one — follow the $ref chain before concluding the field "is not required anywhere."

Version differences that change the answer

draft-04 treats required as an array of strings (required: ["a", "b"]); draft-07+ keeps the array but ecosystem tools differ in error paths. 2020-12 moves definitions to $defs, which breaks schemas whose $ref paths were never updated — the validator then reports every field as missing because the reference resolves to nothing. If required-errors appear on a schema that "worked before", check the validator's draft detection before debugging the data.

How to locate step by step

Open the JSON Schema Validator on ToolVault:

  1. Paste JSON data on the left, Schema on the right;
  2. Click validate — the tool lists all errors (allErrors, not just the first) and shows the path;
  3. Check the path: typo, wrong level, or wrong type;
  4. First format both data and Schema with the JSON Formatter so nesting is clear at a glance;
  5. If the Schema itself must change, adjust it in the JSON Schema editor or reverse-engineer a skeleton with the JSON Schema generator.

Three defensive schema patterns that prevent the class

  1. Explode sneaky $refs during debugging: indirection that saves lines costs hours — inline (or add $id anchors and test resolution explicitly) when errors confuse the team.
  2. Give oneOf a discriminator: bare branches fail with opaque messages on near-matches; a required distinguishing field turns "which branch failed?" into "this field is wrong".
  3. Fixture-test the schema itself: keep one sample document per variant under /fixtures, wire them into CI as must-validate — schemas rot silently, and required-field drift shows up exactly when a partner integration breaks.

Honest boundary: in-browser validation is for local debugging and teaching. Huge schemas, remote $ref fetching, and custom format keywords should still match your server/CI Ajv (or equivalent). The site tool's job is "same payload + schema, every error path immediately, locally."

FAQ

Multiple required missing, but only one reported?

A strict validator may stop at the first; our tool lists all errors so you can fix them in one pass.

Does a wrong type also report as required?

No. Type errors are reported by the type keyword (should be string), independent from required. The keyword field tells them apart.

Can I make "pick one of two required"?

Yes — wrap two required sets in oneOf or anyOf, more flexible than a bare required. Classic "either phone or email":

{
  "anyOf": [
    { "required": ["phone"] },
    { "required": ["email"] }
  ]
}

Prefer oneOf when exactly one variant is allowed, and add a discriminator so errors do not collapse into a single opaque oneOf failure.

Field exists but the value is null — why does it still "pass"?

required checks only that the key is present, never the value. "email": null passes required but fails type: "string". To forbid null too, keep the type as "string" (do not put null in a type union), or add an explicit not: { "type": "null" } clause; in OpenAPI, also check nullable.

Implementation notes

Narrowing down a required error with a diff has one corner that must be handled: big integers parse into a lossless representation, equal values compare by raw numeric text, and unequal instance references don't count as differences — compare by reference and identical long IDs get flagged as modified, sending the investigation off course.


Provided by ToolVault. Related tools: JSON Schema Validator, JSON Schema editor, JSON Schema generator, JSON Formatter, JSON Diff. Visit the home page for more developer tools.