FAQ
schema! or #derive(Validate)?
Both generate the same API. schema! needs no proc-macro and keeps the schema next to the type in one line per field. The derive (feature derive) fits structs that already carry other derives and attributes, supports #[serde(skip)] / default, and generic structs. The derive's parse method is vld_parse() (not parse()) to avoid clashing with clap::Parser::parse.
Why is vld::date() missing?
It exists only when exactly one of the chrono, jiff, time features is enabled. Another crate in your tree may have enabled a second backend. Use vld::chrono::date() (or the backend you use). See Dates.
Why does my runtime limit not change?
Field schemas in schema! / derive structs are built once per process. A value read from configuration is frozen at the first parse. Build such schemas at runtime with vld::object(). See Performance.
How do I return a schema from a function?
Return impl vld::Schema<Output = T>. A plain impl VldSchema hides the JSON Schema traits, so with the openapi feature the result cannot be used as an object or schema! field:
fn username() -> impl vld::Schema<Output = String> {
vld::string().min(3).max(20).alphanumeric()
}
vld::Schema is VldSchema plus, with openapi, JsonSchema and CollectNestedSchemas.
T::vld_parse_value is not found
#[derive(Validate)] and schema! types have an inherent vld_parse_value (and parse_value), so MyType::vld_parse_value works without importing anything. For a generic T: VldParse it comes from the bound.
The compiler says my schema is not Send / Sync / 'static
Same cause: cached field schemas live in a static. Closures in refine, transform or custom must not capture references to local data; move owned data in or use constants.
How do I accept "42" for a number field in JSON?
Use .coerce(): vld::number().coerce(), vld::u32().coerce(), vld::boolean().coerce(). Web query, path, form, header and cookie values are coerced automatically.
How do I reject unknown fields?
vld::object().strict() rejects them with unrecognized_field. schema! and derive structs ignore unknown keys.
Why does a missing field say "Required field is missing" but null says "Expected string, received null"?
Since 0.5 an absent key reports missing_field and a present null reports invalid_type, so clients can tell the two apart. Make the field .optional(), .nullable() or .with_default(..) to accept both.
How do I get the error code in my frontend?
The web adapters include code (the stable IssueCode::key()) in every issue of the 422 body. In Rust, call issue.code.key().
Can I validate a struct I already have?
Yes: User::validate(&user) for schema! / derive types (the value must implement Serialize), impl_rules! for any struct, or schema.validate(&value) for a single schema. See Parse vs validate.
Does vld work in WebAssembly?
The core has no platform-specific code; the UI integrations (vld-leptos, vld-dioxus) are built for wasm32 in CI. Features that touch the filesystem (path().exists(), file()) are not meaningful in a browser.
Is there a TypeScript version of my schemas?
vld-ts generates Zod or Valibot code from vld schemas, so client and server validate the same rules.
Where are the API docs?
On docs.rs/vld. Each integration crate links its own docs.rs page from its integration page.