Skip to content

Max depth

Schemas, lists, maps and unions nest. A recursive schema built with forwardRef() nests as deep as its input does, and untrusted input can be very deep. l.maxDepth is the limit: when a nesting validator sits deeper than that inside the value, validation stops there with a tooDeep issue.

The default is 512, also available as ValidatorFactory.defaultMaxDepth. A tree 100 levels deep validates without touching it.

late final SchemaValidator node;
node = l.schema({
'value': l.string().required(),
'children': l.list(forwardRef(() => node.required())),
});
Object deep(int n) =>
n == 0 ? {'value': 'leaf'} : {'value': 'n$n', 'children': [deep(n - 1)]};
print(l.maxDepth);
print(node.validate(deep(100)).isValid);
512
true

Set l.maxDepth before validating. The setting is read on each validate call, so it applies to validators built earlier. Depth counts every nesting validator on the way down: a schema field is one level, a list element another.

l.maxDepth = 4;
final result = node.validate(deep(5));
print(result);
print(result.issues.single.params);
ValidationFailure(errors: {children.0.children.0.children: [children is nested deeper than 4 levels]})
{maxDepth: 4}
node.validate(input) with l.maxDepth = 4+1-1
  1. valid: deep(1)
  2. invalid: deep(5)children.0.children.0.children: children is nested deeper than 4 levels

The issue is reported at the path where the limit was crossed, with params['maxDepth'] set to the limit.

Input beyond the limit is reported as invalid, never accepted unchecked. That is the point of the guard: a recursive schema facing a hostile payload returns a failure instead of a StackOverflowError.

l.maxDepth = ValidatorFactory.defaultMaxDepth;
512

The setting is global to the isolate, like l.messageBuilder. Set it once at startup rather than around individual calls.