tauri-plugin-configurate provides two layers of validation: manual dry-run checks you call explicitly, and automatic validation wired into read and write operations through the Configurate constructor. Both layers throw an error on failure — no silent data corruption.
Manual validation
validate
config.validate(data) checks a full config object against the schema without touching storage. It throws if any field is missing, has the wrong type, or — when allowUnknownKeys is false — if any undeclared key is present.
try {
config.validate({
theme: "dark",
language: "en",
database: { host: "localhost", password: "secret" },
});
console.log("Data is valid");
} catch (e) {
console.error("Validation failed:", e.message);
}
Use validate before a create or save call when you want to surface type errors to the user before any IPC round-trip.
validatePartial
config.validatePartial(data) checks a partial config object. Only the keys you provide are validated — missing keys are not treated as errors. This mirrors the semantics of patch.
// Validates only the "theme" field; other fields are ignored
config.validatePartial({ theme: "dark" }); // OK
// Passes a wrong type — throws
config.validatePartial({ theme: 123 }); // throws: expected string
Use validatePartial before a patch call to catch type errors on the keys being updated.
Automatic validation on read and write
The Configurate constructor accepts a validation option object that enables automatic validation at the point of storage access.
const config = new Configurate({
schema: appSchema,
fileName: "app.json",
baseDir: BaseDirectory.AppConfig,
provider: JsonProvider(),
validation: {
validateOnWrite: true, // validates data before create/save
validateOnRead: true, // validates data after load/unlock
allowUnknownKeys: false, // rejects keys not declared in the schema
},
});
All three options default to false if omitted.
validateOnWrite
When validateOnWrite is true, every create, save, and patch call runs the schema validator against the data before sending it to the Rust side. A validation failure throws immediately — no IPC call is made.
// With validateOnWrite: true
await config
.save({ theme: 42, language: "en", database: { host: "localhost", password: "secret" } })
.lock(KEYRING)
.run();
// throws: expected string for "theme"
Enable validateOnWrite in development to catch schema mismatches early. In production, you may prefer to leave it off and rely on TypeScript inference alone, since the type system already prevents most mismatches at compile time.
validateOnRead
When validateOnRead is true, every load and unlock call runs the schema validator against the data returned from storage. A validation failure throws — no data is returned.
// With validateOnRead: true
const locked = await config.load().run();
// throws if the stored file contains a field with the wrong type
This protects against external edits that introduce type mismatches (for example, someone manually editing app.json and setting fontSize to a string). It also catches schema drift when a migration was skipped.
allowUnknownKeys
When allowUnknownKeys is false (the default), the validator rejects data objects that contain keys not declared in the schema. Set it to true if you want to tolerate extra fields — useful during a schema transition when on-disk files may contain fields that your new schema no longer declares.
const config = new Configurate({
schema: appSchema,
fileName: "app.json",
baseDir: BaseDirectory.AppConfig,
provider: JsonProvider(),
validation: {
validateOnRead: true,
allowUnknownKeys: true, // allows legacy keys to pass through without error
},
});
Error handling
Both validate and validatePartial throw a standard JavaScript Error. The message describes the field path and the expected type.
try {
config.validate({ theme: 99, language: "en", database: { host: "localhost", password: "x" } });
} catch (e) {
// e.message: something like "Expected string for key 'theme', got number"
console.error(e.message);
}
Automatic validation triggered by validateOnWrite or validateOnRead also throws a standard Error, which will reject the returned promise.
Choosing an approach
| Use case | Recommended approach |
|---|
| Validate user input before writing | config.validatePartial(patch) or config.validate(data) |
| Catch schema mismatches on every write | validation.validateOnWrite: true |
| Detect corrupt or externally modified files on load | validation.validateOnRead: true |
| Allow files with extra keys from an older schema version | validation.allowUnknownKeys: true |
| TypeScript compile-time safety only (no runtime overhead) | Leave all validation options at their defaults (false) |