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

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, the codebase defines a single source of truth for the expected format:

// 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 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:

// 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 (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.

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:

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:

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 Defines SCHEMA_VERSION, the Config struct, and migration documentation
crates/openlogi-core/src/config/file.rs Implements file-reading logic with version checking and migrations
docs/config.example.toml Example user configuration showing proper schema_version header
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 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 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 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →