← Back to blog

n8n data validation: an exercise before company-record writes

Practise n8n data validation with synthetic company records: identify missing, empty and invalid fields, retain correction reasons and inspect both routing paths.

Company records pass an n8n data validation gate or move into a separate correction tray.

Checked against the cited sources on .

Your n8n data validation task and boundaries

This editorial exercise asks you to build n8n data validation that sends accepted company records toward a write boundary and keeps rejected records available for correction. Use synthetic inputs, preserve each original record and explain every rejection. The proposed workflow and expected results have not been executed or validated.

You need an n8n environment with JavaScript Code node support, basic JavaScript knowledge and access to node outputs. n8n documents custom JavaScript steps and a default Run Once for All Items mode; the supplied documentation establishes no specific edition or version. Check Object.hasOwn() support in your runtime if you use an older installation.

Stop at an inspection point representing the intended write boundary. Destination configuration and actual create or update operations are outside scope. We think making rejection reasons reviewable is as important as producing an accepted payload.

Sources: n8n-docs/docs/reusable-content/.gitbook/includes/integrations/builtin/core-nodes/code-node.md at main · n8n-io/n8n-docs · GitHub, Object.hasOwn() - JavaScript | MDN

Define the contract and synthetic inputs

Company-record specimens show an absent field, an empty field and a field containing the wrong type.
The specimen trays distinguish missing, empty and wrong-type inputs used in the editorial exercise.

Use this editorial contract: companyName and contactEmail must exist, contain non-null strings and remain non-empty after trimming. contactEmail must also pass n8n's documented isEmail() format check. These are exercise rules, not universal company-record requirements. The email check does not establish mailbox existence, ownership or deliverability; its accepted grammar is not specified in the supplied source.

Prepare the suggested cases below for n8n data validation. Every record has its listed caseId; unspecified fields use companyName = Acme and contactEmail = hello@example.com. Quotation marks indicate string values, while null, numbers and booleans indicate their corresponding types. The decisions and reasons are proposed expectations.

Editorial fixtures and proposed expectations
caseIdChange from baselineDecisionExpected reasons
C01NoneAcceptNone
C02Omit companyNameRejectcompanyName: missing
C03companyName = nullRejectcompanyName: empty
C04companyName = ""RejectcompanyName: empty
C05companyName = " "RejectcompanyName: empty
C06companyName = 42RejectcompanyName: invalid_type
C07contactEmail = falseRejectcontactEmail: invalid_type
C08contactEmail = "hello"RejectcontactEmail: invalid_email
C09companyName = " "; contactEmail = "hello"RejectcompanyName: empty; contactEmail: invalid_email
C10companyName = " Acme "AcceptNone
C11companyName = 0RejectcompanyName: invalid_type

Sources: n8n-docs/docs/build/work-with-data/transform-data/expression-reference/string.md at main · n8n-io/n8n-docs · GitHub

Suggested solution: inspect fields and retain reasons

For n8n nodes, data validation in this exercise separates field inspection from routing. Start with a JavaScript Code node in Run Once for All Items mode. Read $input.all() and process every item, whose ordinary data sits under json. Return one json-wrapped result per input containing caseId, original, normalized, validationErrors and isValid; keep validation metadata outside the original record.

Follow this suggested algorithm for each required field. Object.hasOwn() distinguishes an absent property from a present one, including one containing null or undefined. Check null separately because JavaScript's typeof reports it as an object. Check string type before trim(), which returns a new string without changing the original.

  1. If the field is not an own property, append its missing reason and stop checking that field.
  2. If its value is null or undefined, append empty and stop checking that field.
  3. If its type is not string, append invalid_type and stop checking that field.
  4. Trim the string into normalized; if it is empty, append empty.
  5. Continue with the other required field so simultaneous failures remain visible.

Treat email format as a separate n8n expression check using normalized.contactEmail.isEmail(), reached only for a non-empty string. Carry its result into a final JavaScript step that appends contactEmail: invalid_email when false, then sets isValid from validationErrors.length === 0. This avoids assuming that n8n expression helpers are ordinary JavaScript methods.

n8n's 2026 Production AI Playbook illustrates validationErrors and an isValid flag for AI output; this exercise adapts that pattern to company records. In our view, one precise reason per failed field is more useful here than cascading several errors from the same missing value.

Sources: n8n-docs/docs/reusable-content/.gitbook/includes/integrations/builtin/core-nodes/code-node.md at main · n8n-io/n8n-docs · GitHub, n8n-docs/docs/build/work-with-data/transform-data/expression-reference/README.md at main · n8n-io/n8n-docs · GitHub, n8n-docs/docs/build/work-with-data/understand-n8ns-data-structure.md at main · n8n-io/n8n-docs · GitHub, Object.hasOwn() - JavaScript | MDN, typeof - JavaScript | MDN, String.prototype.trim() - JavaScript | MDN, n8n-docs/docs/build/work-with-data/transform-data/expression-reference/string.md at main · n8n-io/n8n-docs · GitHub, Production AI Playbook: Deterministic Steps & AI Steps – n8n Blog

Route records and check completion

Use an If node to compare isValid with Boolean true. n8n documents conditional splitting through comparison operations. Connect the true branch to the inspection point and the false branch to review; do not reconnect review to the write path. The following checklist defines the proposed completion criteria for your n8n data validation exercise.

Inspect both branch outputs and execution history. n8n's 2026 API Contract Testing article recommends retaining execution history as validation evidence. This dry run demonstrates routing only; establishing that an external destination received no writes requires a separate sandbox destination check.

For unexpected decisions, inspect field spelling, null handling, type checks before trim(), Boolean versus string comparisons, caseId preservation and branch connections. Suggested reflection: why does a present null differ from an absent key, and what evidence would justify changing one rejection rule?

Sources: Object.hasOwn() - JavaScript | MDN, typeof - JavaScript | MDN, String.prototype.trim() - JavaScript | MDN, n8n-docs/docs/integrations/builtin/core-nodes/n8n-nodes-base.if.md at main · n8n-io/n8n-docs · GitHub, API Contract Testing: Prevent Downstream Failures — n8n Blog – n8n Blog

Put this into practice

Hands-on n8n challenges

Pick a challenge and build a working workflow in your own n8n environment, with five progressive tips per challenge.

Try a hands-on challenge

For your team

Custom n8n training programs for one team or department, run on your own n8n instance with your own tools and data.

Training for your team

n8n skills assessment

A free quiz of about 20 minutes: 30 questions in 10 skill areas and a level from Beginner to Expert. On AI Adoption Score, another project by the author of this site.

Get your n8n level