Resource limits¶
A validator runs against untrusted values, so every recursive descent and every
error-reporting probe is bounded. A pathological input meets a gated limit and is
rejected cleanly; it never overflows the native stack, raises a Python
RecursionError, or hangs. The limits bound work driven by the value — the
untrusted part. A schema's own size (the width of a union, the number of declared
fields) is written by the developer and is trusted.
The bounds¶
- Schema build depth. A schema nested past a fixed depth is rejected when the
validator is compiled, not at validation time. A self-referential class is the
usual cause; model it with
recursiveinstead. - Value-walk depth. A value nested past a fixed depth fails with
recursion_limitrather than recursing into the native stack. This holds on both the object path and the JSON path; an over-deep JSON document is rejected by the parser asjson_invalid. - Self-reference. A value that contains itself is caught by an
object-identity guard and fails with
recursion_looprather than looping forever. - Closest-branch probe. When a value misses a wide union, the error report searches only a bounded number of branches for the closest match, so building the explanation stays bounded regardless of how the value is shaped.
Rejection is clean, not catastrophic¶
from valgebra import ValidationError, Validator, recursive, union
schema = Validator(recursive(lambda j: union(int, [j])))
# A value nested far past the walk depth: a clean error, not a crash.
deep = 0
for _ in range(5000):
deep = [deep]
assert not schema.is_valid(deep)
try:
schema.validate(deep)
except ValidationError as error:
assert error.code == "recursion_limit"
# A value that contains itself: caught as a loop.
cyclic = []
cyclic.append(cyclic)
assert not schema.is_valid(cyclic)
# An over-deep JSON document: rejected by the parser.
assert not schema.is_valid_json("[" * 5000 + "1" + "]" * 5000)
The worst-case timing of these shapes is measured by the adversarial benchmark and the bounds are correctness-tested, so each limit is an enforced, exercised guarantee rather than a comment.