# Understanding `schema_version` in OpenLogi Configuration: Why It Protects Your Settings

> Discover the significance of schema_version in OpenLogi configuration. Learn how it protects your settings from data loss and ensures compatibility with automatic migrations and future updates.

- Repository: [Xuan Zhang/OpenLogi](https://github.com/AprilNEA/OpenLogi)
- Tags: deep-dive
- Published: 2026-09-01

---

**The `schema_version` field in OpenLogi configuration files acts as a version gate that prevents data loss, enables automatic migrations from older formats, and blocks loading of unsupported future formats.**

OpenLogi, an open-source input device management tool written in Rust, stores user settings in TOML configuration files. The `schema_version` field serves as the critical mechanism that ensures safe upgrades and maintains compatibility across different releases of the `openlogi-core` crate.

## What `schema_version` Controls in OpenLogi

At the core of OpenLogi's configuration system lies a simple integer that governs every aspect of file loading and validation. This value determines whether your settings load cleanly, get transparently upgraded, or fail with a clear error message.

### The Current Version Constant

In [`crates/openlogi-core/src/config.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/config.rs), the codebase defines a single source of truth for the expected format:

```rust
// From config.rs lines 48-55
pub const SCHEMA_VERSION: i64 = 7;

```

This constant represents the latest supported configuration format. Every TOML file read by OpenLogi must declare its own `schema_version` at the top level, and the loader uses this declaration to decide how to proceed.

## Version Gating: Blocking Incompatible Configurations

When `ConfigFile::load()` processes a configuration file, it performs strict validation against the stored `schema_version`. The implementation in [`config.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/config.rs) rejects two specific cases that would risk data integrity:

1. **Version 0** — Indicates corrupted or uninitialized files
2. **Versions newer than current** — Prevents silent failures when opening files created by future OpenLogi releases

The validation logic at lines 90-93 produces explicit errors rather than attempting unsafe parsing:

```rust
// Simplified representation of the version check
if file_version == 0 || file_version > SCHEMA_VERSION {
    return Err(ConfigError::UnsupportedVersion(file_version));
}

```

This guards against the common problem where older software silently misinterprets newer configuration formats, leading to lost settings or unexpected behavior.

## Automatic Migrations: Preserving Older Configurations

OpenLogi maintains backward compatibility through a documented migration pipeline. For schema versions 1 through 6, the loader applies sequential transformations that bring legacy configurations up to the current format before use.

The comment block in [`config.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/config.rs) (lines 56-90) catalogs each historical change:

- **v7** — Introduction of thumb-wheel defaults
- **v6** — Threshold-based button bindings
- **v5** — Transport-scoped keys and UI-scale addition
- **v4** — Removal of owner-lock functionality
- **v3** — Device-key format changes
- **v2** — Merging of binding maps

These migrations run automatically based on the detected `schema_version`, ensuring users never need to manually edit configuration files when upgrading OpenLogi.

## Default Configuration Generation

When creating fresh configurations via `Config::default()`, the system automatically injects the current `SCHEMA_VERSION`. This self-healing behavior guarantees that any file written by the running binary remains compatible with future releases of the same version.

```rust
use openlogi_core::config::{Config, ConfigFile};
use std::path::PathBuf;

// Create a fresh config — version 7 is set automatically
let cfg = Config::default();
assert_eq!(cfg.schema_version, Config::SCHEMA_VERSION); // → 7

```

## Practical Examples: Working with `schema_version`

### Loading and Migrating Existing Configurations

The `ConfigFile::load()` method handles both validation and migration transparently:

```rust
let path = PathBuf::from("/home/user/.config/openlogi/config.toml");

match ConfigFile::load(&path) {
    Ok((config, file_version)) => {
        println!("Loaded config version {file_version}");
        // config is now in the latest shape, regardless of original version
    }
    Err(e) => eprintln!("Failed to read config: {e}"),
}

```

### Handling Rejected Future Versions

Attempting to load a configuration from a future OpenLogi release produces a clear error:

```rust
let future_config = r#"schema_version = 99
selected_device = "mouse"
"#;

match toml::from_str::<Config>(future_config) {
    Ok(_) => println!("Unexpectedly succeeded"),
    Err(e) => println!("Correctly rejected: {e}"),
}

```

This prevents the silent data corruption that would occur if the parser attempted to interpret unknown fields.

## Key Source Files for `schema_version` Implementation

| File | Purpose |
|------|---------|
| [`crates/openlogi-core/src/config.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/config.rs) | Defines `SCHEMA_VERSION`, the `Config` struct, and migration documentation |
| [`crates/openlogi-core/src/config/file.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/config/file.rs) | Implements file-reading logic with version checking and migrations |
| [`docs/config.example.toml`](https://github.com/AprilNEA/OpenLogi/blob/main/docs/config.example.toml) | Example user configuration showing proper `schema_version` header |
| [`crates/openlogi-core/src/binding/action.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding/action.rs) | Demonstrates that enum variant changes require schema bumps |

The connection between schema versions and enum vocabularies in [`action.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/action.rs) illustrates how `schema_version` protects not just data structure but also semantic meaning across releases.

## Summary

- **`schema_version` is the compatibility gatekeeper** — Every OpenLogi configuration file declares its format version through this required field
- **Strict validation prevents data loss** — Files with version 0 or versions exceeding the current `SCHEMA_VERSION` (7) are rejected with explicit errors
- **Automatic migrations preserve user settings** — Configurations from versions 1-6 are transparently upgraded to the current format
- **Self-healing defaults ensure consistency** — New configurations automatically receive the current schema version

## Frequently Asked Questions

### What happens if I manually edit `schema_version` in my config file?

**Manual changes to `schema_version` will likely cause loading failures.** Setting it to 0 or a value higher than your OpenLogi build supports triggers the version gate error. Setting it lower than the actual format may cause parsing failures or silent misinterpretation of fields. Always let OpenLogi manage this value through its official APIs.

### Does OpenLogi support downgrading configurations to older schema versions?

**No, OpenLogi does not implement downward migrations.** The migration system only upgrades older formats to the current `SCHEMA_VERSION`. If you need to use an older OpenLogi release, you must either use a backup configuration from that era or recreate your settings.

### How do I know when a schema version bump affects my configuration?

**Review the migration comments in [`config.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/config.rs) when upgrading.** The documented changelog at lines 56-90 explains what changed in each version. Additionally, changes to binding-related enums in files like [`crates/openlogi-core/src/binding/action.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding/action.rs) typically require version bumps, signaling potential impact to your device mappings.

### Can I use the same configuration file across multiple machines with different OpenLogi versions?

**Only if all versions share compatible schema support.** The safest approach is running identical OpenLogi versions across machines, or ensuring older versions never write to files newer versions will read. The `schema_version` system explicitly prevents newer-format files from loading on older builds to protect against corruption.