Parameter Schemas for Validation and Surprise Checking
The schema validator supports a focused subset of JSON Schema , along with a few Conduit-specific extensions under constraints.
Defined in:
src/libs/flow/flow_schema_validator.hppsrc/libs/flow/flow_schema_validator.cpp
The validator is designed to validate Conduit nodes against a schema expressed as another Conduit node.
Note
When writing schemas for this validator, assume:
only the fields documented here are supported
unsupported JSON Schema keywords are ignored unless explicitly handled by the validator
several behaviors differ from standard JSON Schema because they are adapted to Conduit’s data model
API Surface
The public API is:
bool flow::schema::validate(const conduit::Node &schema, const conduit::Node &input, conduit::Node &info);void flow::schema::set_expression_checker(ExpressionCheckFn fn);
validate returns true on success. On failure, info["errors"] is
populated with one or more human-readable error strings.
Quick Usage Pattern
A schema is itself a Conduit node that describes the expected structure of an input node.
A typical object schema looks like this:
{
"type": "object",
"required": ["name"],
"properties": {
"name": {
"type": "string",
"minLength": 1
},
"count": {
"type": "integer"
}
},
"additionalProperties": false
}
In pseudocode, validation looks like:
conduit::Node schema; // schema definition
conduit::Node input; // node to validate
conduit::Node info; // receives errors
const bool ok = flow::schema::validate(schema, input, info);
If ok is false, read info["errors"] (a list of strings) for details.
Supported Keywords
type
The validator uses
schema["type"](a string) to decide which validations to apply. Supported types are:
object: A conduit object node
string: A string leaf node
number: Any numeric type
integer: Any integer type
array: a Conduit list, a Conduit object, or a numeric leaf array (a numeric node withnumber_of_elements() >= 1).Note
Empty input nodes (
dtype().is_empty()) are treated specially:
If the schema
typeis"object"and the input is empty, the validator validates as if the input were an empty Conduit object.If the schema
typeis"array"and the input is empty, the validator validates as if the input were an empty Conduit list.Warning
Unknown
typevalues are reported as schema errors.Example:
# Schema: non-empty string type: string minLength: 1Validation Failure Example (type mismatch)
# Schema type: string # Input 42Validation failed at '<root>' (type): type mismatch. Expected type 'string'.
format
Format checking is an additional layer of string validation that allows for the input strings to be validated against a given format. Formats can be registered with the schema validator using
register_format_checker(const std::string &format_name, bool (*)(const std::string &expr, std::string &err_msg) callback). Once a format is registered, it can be refrenced in the schemas using the format name they were registered with.Example:
If you had the following function to check if a string matches a specific expression grammar:
bool is_valid_expression(const std::string &expr, std::string &err_msg) { bool res = true; try { scan_string(expr.c_str()); } catch(const char *msg) { err_msg = msg; res = false; } return res; }You could register it with the schema validator:
flow::schema::register_format_checker("expression", &is_valid_expression);and then use it in any schemas to validate strings:
type: string format: expression
enum
Restricts a string input to one of the allowed values.
The validator only applies
enumwhen the input value is a string.The allowed list is expected to be a list of strings in the schema.
Example:
type: string enum: ["nearest", "linear"]Validation Failure Example (enum mismatch)
# Schema type: string enum: ["nearest", "linear"] # Input "furthest"Validation failed at '<root>' (enum): 'furthest' is not one of the allowed enum entries. Expected one of {nearest, linear}.
allOf
Requires that the input validates against all subschemas in the array.
On failure, the validator records a summary message and may add a small number of per-option “hint” messages derived from the first error in each failing option.
Example:
# Require multiple constraints at once. allOf: - {type: string, minLength: 1} - {type: string, pattern: "^[a-z0-9_]+$"}Validation Failure Example (string not matching all schemas)
# Schema allOf: - {type: string, minLength: 1} - {type: string, enum: ["nearest", "linear"]} # Input "furthest"Validation failed at '<root>' (all of): expected all of the 2 schema options to match, but only one matched Option 0 hint: Validation failed at '<root>' (enum): 'furthest' is not one of the allowed enum entries. Expected one of {nearest, linear}.
oneOf
Requires that the input validates against exactly one subschema in the array.
On failure, the validator records a summary message and may add a small number of per-option “hint” messages derived from the first error in each failing option.
Example:
# Accept exactly one option; keep ranges non-overlapping to avoid ambiguity. oneOf: - {type: integer, maximum: 9} - {type: integer, minimum: 10}Validation Failure Example (no matching option; note the per-option hints)
# Schema oneOf: - {type: integer, maximum: 5} - {type: integer, minimum: 10} # Input 8Validation failed at '<root>' (one of): expected exactly one of 2 schema options to match, but none matched. Option 0 hint: Validation failed at '<root>' (maximum): 8 is above the allowed maximum. Expected number <= 5. Option 1 hint: Validation failed at '<root>' (minimum): 8 is below the allowed minimum. Expected number >= 10.
anyOf
Requires that the input validates against at least one subschema in the array.
On failure, the validator records a summary message and may add a small number of per-option “hint” messages derived from the first error in each failing option.
Example:
# Accept either a string name or an integer id. anyOf: - {type: string, minLength: 1} - {type: integer, minimum: 0}Validation Failure Example (no matching option; note the per-option hints)
# Schema anyOf: - {type: integer, maximum: 5} - {type: integer, minimum: 10} # Input 8Validation failed at '<root>' (any of): input did not match any allowed schema option. Expected at least one schema option to match. Option 0 hint: Validation failed at '<root>' (maximum): 8 is above the allowed maximum. Expected number <= 5. Option 1 hint: Validation failed at '<root>' (minimum): 8 is below the allowed minimum. Expected number >= 10.
String Keywords (type: "string")
minLength
Requires the string length to be at least this integer value.
Example:
type: string minLength: 3Validation Failure Example
# Input "ab"Validation failed at '<root>' (minLength): string is too short. Length is 2. Expected string length >= 3.
maxLength
Requires the string length to be at most this integer value.
Example:
type: string maxLength: 8
pattern
Requires the string to match the regular expression pattern.
Note
The validator uses C++
std::regexand checks withstd::regex_search(i.e., the pattern may match any substring; it is not implicitly anchored). To require a full-string match, add anchors (e.g.,^...$).Invalid regex patterns are reported as schema errors.
Example:
type: string
pattern: "^[a-z]+$"
Validation Failure Example (pattern mismatch)
# Shema
type: string
pattern: "^A+$"
# Input
"Abc"
Validation failed at '<root>' (pattern): string does not match required pattern '^A+$'.
Validation Failure Example (schema error from invalid regex)
# Schema
type: string
pattern: "["
# Input
"anything"
Schema error near '<root>' (pattern): invalid regex pattern '['.
Numeric Keywords (type: "number" / type: "integer")
minimum
Requires the numeric value to be
>= minimum.Example:
type: number minimum: 0.0Validation Failure Example
# Input -1.0Validation failed at '<root>' (minimum): -1.000000 is below the allowed minimum. Expected number >= 0.
exclusiveMinimum
Requires the numeric value to be
> exclusiveMinimum.Example:
type: number exclusiveMinimum: 0.0
maximum
Requires the numeric value to be
<= maximum.Example:
type: number maximum: 1.0
exclusiveMaximum
Requires the numeric value to be
< exclusiveMaximum.Example:
type: number exclusiveMaximum: 1.0
Object Keywords (type: "object")
properties
Declares named subschemas for object children.
The validator only validates properties that are present in the input. Missing properties are not an error unless required by
required.Example (used below with
requiredandadditionalProperties):type: object additionalProperties: false properties: name: {type: string, minLength: 1} count: {type: integer, minimum: 0} required: [name, count]
required
A list of string field names that must be present on the input object.
Example:
type: object properties: name: {type: string} required: [name]
additionalProperties
If present and falsey (
to_int() == 0), forbids any input object children not declared inproperties. This is equivalent to enforcing “surprise checking” against the schema.If the keyword is not present, additional properties are allowed.
Example:
type: object additionalProperties: false properties: name: {type: string}Validation Failure Example
# Input name: "ok" debug: "nope"Validation failed at 'debug' (additionalProperties): unexpected additional field is not allowed here.
Array Keywords (type: "array")
minItems
Requires the array length to be at least this integer value.
Example:
type: array minItems: 1
maxItems
Requires the array length to be at most this integer value.
Example:
type: array maxItems: 3
items
A subschema applied to each element of the input.
Notes:
For Conduit lists and objects, elements are accessed via
child(i).For Conduit numeric leaf arrays, each element is validated by aliasing the i’th element as an external scalar node and applying the
itemsschema.Example:
type: array minItems: 1 maxItems: 3 items: {type: integer, minimum: 0}
Non-Standard Keywords (constraints/*)
The validator supports several extra keywords under a constraints object.
These are not standard JSON Schema keywords, but they allow for more flexible
and explicit validation schemas.
constraints/skip
If present and truthy (
to_int() != 0), validation for that schema node is skipped entirely (it always succeeds).Example:
type: object constraints: skip: trueNote
This additional feature allows for schemas to be defined without being explicitly validated against or surprise checked. This allows for subsets of a schema to be validated while the remainder of the schema can be ignored or validated at a later time.
constraints/forbid
For object inputs only. A list of string field names that must not be present.
Example:
type: object constraints: forbid: ["debug", "internal_only"]Note
Standard JSON Schema can express “forbidden properties”, but it is verbose (typically involving nested
not+requiredcombinations). This keyword is a compact way to enforce deprecations, feature gating, or to block internal knobs from user-facing schemas while keeping the rest of the object open to evolution.
constraints/const
Requires the input to exactly match a constant value.
Supported constant types in the schema are:
string
integer
number
Unsupported constant types are reported as schema errors.
Example:
# Require a fixed string "v1" constraints: {const: "v1"}Note
Standard JSON Schema has a top-level
constkeyword, but this validator nests some non-standard rules underconstraints. Keeping const here allows schemas to group “extra constraints” together and keeps the validator’s behavior explicit and easy to scan in Conduit/YAML.
constraints/not_const
For object inputs only. Forbids specific constant values for specific fields.
The schema value is expected to be an object whose children are field names, where each field maps to a forbidden constant value (string, integer, or number). If the input contains that field with the same value, validation fails.
Example:
type: object constraints: not_const: mode: "unsafe" retries: 0Note
This is a concise way to ban specific values (e.g.,
mode: "unsafe"orretries: 0) without rewriting the entire field schema or adding complex boolean logic. In standard JSON Schema this typically requires multiplenotclauses that can be harder to read and maintain.
constraints/dependencies
For object inputs only. Declares field dependencies.
The schema value is expected to be an object mapping a trigger field name to a list of required field names. If the trigger field is present in the input, all required fields must also be present.
Example:
type: object constraints: dependencies: output_path: ["output_protocol"]Note
JSON Schema dependency tracking varries between versions of JSON schema. This validator elected to match the language used in Draft 7. Similarly to
constraints/const, standard JSON Schema generally has dependencies at the tope level, but this validator elects to store them under constraints. Keeping const here allows schemas to group “extra constraints” together and keeps the validator’s behavior explicit and easy to scan in Conduit/YAML.
constraints/exclusiveChildren
For object inputs only. Declares a list of mutually-exclusive field names.
By default, the validator allows zero or one of the listed fields to be present. If more than one is present, validation fails.
Example:
type: object constraints: exclusiveChildren: ["file", "buffer"]Note
Mutually-exclusive property groups are common in parameter schemas (“choose one of these ways to specify the input”). Standard JSON Schema can encode this with
oneOfand multiplerequired/notcombinations, but the result is verbose and difficult to maintain as the option set grows. This keyword provides a consise and simple approach to this functionality.
constraints/allowNoneInExclusiveGroup
Only used with
constraints/exclusiveChildren.If present and falsey (
to_int() == 0), the validator requires exactly one of the mutually-exclusive fields to be present (it becomes an error if none are present).Example (require exactly one instead of zero-or-one):
type: object constraints: exclusiveChildren: ["file", "buffer"] allowNoneInExclusiveGroup: falseNote
Many schemas want “exactly one” while others want “zero or one” (optional selection). This keyword extends the
constraints/exclusiveChildrenkeyword and allows schemas to toggle between the two behaviors.