Core: Other Errors (Governance, Identity, Names, Storage)
Crate: kinetic-core
Stage: 8
Reading Time: 35 minutes
Depends On: kinetic-core/src/error/mod.rs
What Is This?
This file provides comprehensive documentation for four highly specialized and critical error domains within the Kinetic network. These domains are:
- Governance execution.
- Identity validation.
- Name registration.
- Persistent storage.
These error modules are located in
kinetic-core/src/error/governance.rs,kinetic-core/src/error/identity.rs,kinetic-core/src/error/names.rs, andkinetic-core/src/error/storage.rsrespectively. Rather than relying on generic, network-wide error enumerations, these modules carve out highly specific, domain-isolated taxonomies. This deep isolation ensures that when a failure occurs in a very specific subsystem, the error is perfectly tailored. For example, if the embedded Sled database fails to acquire a file lock, or a governance proposal lacks the required cryptographic signatures, the resulting error code is precise. The resulting error code, severity level, and user-facing message are perfectly tailored to that specific context. By separating these, Kinetic avoids a massive, monolithicErrorenum that would require recompiling the world every time a single naming rule changes. It also allows us to implement very specificis_retryable()logic for each distinct domain.
Why Kinetic Needs This
Kinetic is designed as a fully autonomous network. This means it requires built-in sub-protocols for self-management, persistence, and human interaction. Each of these sub-protocols has unique constraints and failure conditions. These constraints simply cannot be mapped to generic “bad request” or “internal server error” paradigms.
-
Governance (
KIN-GOV-NNN): The Kinetic network rules are updated dynamically via on-chain governance. This involves cryptographic thresholds, timelocks, and state machines. If a node attempts to process a proposal that doesn’t meet the required threshold of signatures, it must be rejected. If a node hasn’t waited the required timelock period, the governance engine must reject it explicitly. The network operators need to know exactly why a proposal was rejected. Was it too old? Was it improperly signed? Was it structurally invalid? These precise codes ensure operators can debug their governance CLI tools effectively. Without these specific errors, governance would be a black box of failed state transitions. -
Identity (
KIN-IDN-NNN): Every Kinetic node relies on a local, quantum-resistant ML-DSA-65 identity key. This identity is used to sign its messages. This identity is the foundational anchor of network trust. If a node boots up and cannot read, parse, or decrypt its identity file, it cannot participate in the network. It must halt immediately and alert the operator. Silently generating a new identity would result in the loss of all reputation. It would also result in the loss of routing history associated with the old key. Therefore, the daemon needs granular errors to differentiate between a bad password and a corrupted file. -
Names (
KIN-NAM-NNN): Kinetic provides a decentralized naming system. This allows human-readable apex names (likesaif.kin). To maintain order and compatibility, we must strictly enforce global standards. Specifically, we enforce RFC 1035 and RFC 5891 limits. Furthermore, the network must protect reserved infrastructure names (likeseedorexplorer). This protects them from being squatted by early adopters. When a registration transaction violates these rules, the client needs a clear, actionable error. This allows the wallet software to present a helpful message to the end user. -
Storage (
KIN-STO-NNN): Kinetic relies on the Sled embedded B-tree database for local data persistence. Embedded databases run within the daemon process itself. This means they are highly sensitive to file locks and abrupt process termination. If a user tries to run two Kinetic daemons targeting the same storage directory, Sled will hit a file lock constraint. This needs to be trapped and bubbled up as a critical error (KIN-STO-001). This prevents catastrophic data corruption. A generic IO error would not adequately explain the severity of this lock contention.
How It Works
These four error modules implement the standard Kinetic error taxonomy traits.
This means they each define specific functions to standardise network-wide errors.
The required functions are code(), severity(), user_message(), error_type_uri(), and is_retryable().
However, the logic inside these implementations is deeply tied to the business rules of their respective domains.
1. Governance Validation Logic
-> See: kinetic-core/src/error/governance.rs — Lines 23 to 57
When a Kinetic node receives a SignedGovernanceMessage, the active GovernanceEngine intercepts the message.
This engine can be configured in network.json as sovereign, council, or permissionless.
The engine begins a rigorous verification sequence.
This sequence must pass completely before any state mutation is allowed.
-
The Missing Root Key Crisis: The network must have an anchor of trust. During initialization, the engine checks for the
ROOT_PUBLIC_KEY_HEXenvironment variable. If this is completely missing, the node yieldsGovernanceError::MissingRootKey. Because a node cannot evaluate founder-level overrides or verify network genesis state without this key, this is a fatal condition. The daemon will likely log this and invoke an immediate exit. -
Cryptographic Key Validation: Governance actions often carry public keys for rotation or delegation. Since Kinetic uses ML-DSA-65, these public keys must be exactly 1,952 bytes long. If a provided byte slice does not match this strict length requirement,
KeyLengthMismatchis returned. This prevents malformed payloads from wasting CPU cycles in the signature verification engine. -
Time Windows and Replay Protection: The engine evaluates the timestamp embedded in the governance proposal. If the timestamp is older than the globally allowed replay window, it returns
StaleProposal. The network sees old proposals drifting through gossip protocols all the time. Rejecting them is routine maintenance, not a critical fault. -
Quorum and Thresholds: For networks operating under the
councilengine, a proposal must accumulate a specific threshold of signatures. These signatures must come from valid, active council members. If a proposal attempts execution before hitting this threshold, the engine returnsInsufficientSignatures. -
Mandatory Timelocks: To prevent governance attacks where a malicious quorum pushes a sudden change, proposals have mandatory delay periods. If the
TimelockNotExpirederror occurs, the network is simply enforcing patience. The operator must wait for the timelock window to naturally expire. -
State Machine Compliance: Governance actions flow through a strict state machine. You can only execute or veto a proposal that is currently in a
pendingstate. Attempting to act on a hash that is already finalized or unknown yieldsNotPendingOrVetoed. -
Mode Restrictions: If a node operator explicitly configures their
network.jsonto bepermissionless, they are changing the node’s behaviour. They are declaring that their node will not accept any global governance updates. Any incoming governance action is immediately rejected withGovernanceDisabled. -
Special Naming Actions: Governance has the power to forcefully grant or revoke names. However, rules still apply even to root authorities. Premium names must be exactly 1 character long. Violating this yields
InvalidPremiumNameLength. Infrastructure name grants must target a valid Category 2 list. Violating this yieldsInvalidInfrastructureName.
2. Node Identity Loading Sequence
-> See: kinetic-core/src/error/identity.rs — Lines 13 to 33
The node identity subsystem is the very first component that executes when the Kinetic daemon starts. It dictates whether the node has the cryptographic authorization to join the network.
-
Disk I/O and File Access: The daemon attempts to locate and open
{base_dir}/identity.key. If there is a filesystem permissions issue, a missing directory, or a hardware failure, an error is generated. This is a standard librarystd::io::Error. It is wrapped in theIdentityError::Iovariant. -
File Integrity Checks: If the file is successfully read, the daemon evaluates its size and structure. If the byte length does not match the strict layout of an encrypted ML-DSA-65 key payload, the engine aborts. It yields
CorruptedIdentityFile. This is a critical safety check to prevent parsing garbage data. -
Decryption Protocol: Identity files are protected. If the node operator provides an incorrect password via the environment or prompt, decryption fails. Additionally, if the cryptographic Message Authentication Code (MAC) on the payload fails validation, it also fails. In either case,
DecryptionFailedis triggered. -
Missing File Scenarios: If the file is simply absent (
IdentityNotFound), the daemon’s bootloader must decide how to handle it. In a fresh install, it might silently generate a new key. But if the file is expected (e.g., restarting an existing node), this error forces the daemon to halt. -
Seed Phrase Parsing: Kinetic allows node operators to restore their identity from a human-readable BIP-39 mnemonic seed phrase. If the user provides a phrase that has an invalid word count, it fails. If it fails the dictionary lookup, it fails. If it fails the checksum validation, it fails. Any of these failures results in
InvalidSeedPhrase.
3. Naming System Enforcement Engine
-> See: kinetic-core/src/error/names.rs — Lines 15 to 44
The Kinetic naming system allows users to claim short, human-readable identifiers.
When a user submits a registration transaction to the network, it is intercepted.
It is intercepted by the is_valid_apex_name function, which enforces global standards.
-
RFC 5891 LDH Compliance: The naming engine iterates through every character in the requested name. If it finds emojis, uppercase letters, spaces, or special symbols, it instantly fails. The error yielded is
InvalidCharacter. The LDH rule (Letters, Digits, Hyphens) is heavily enforced to ensure cross-platform compatibility. -
RFC 1035 Length Constraints: To prevent network spam and ensure memory bounds, the entire name string is capped. It is capped at a maximum of 253 characters, yielding
NameTooLongif exceeded. Furthermore, any single label (the word between dots, if applicable) is strictly capped. It is capped at 63 characters, yieldingLabelTooLongif exceeded. -
Hierarchy and Apex Enforcement: The global Kinetic DHT is designed to handle top-level domains and apex names, not infinite sub-trees. If a user attempts to register a deeply nested subname directly on the global network, it fails. The
NotAnApexNameerror enforces the rule that subnames must be managed locally by the apex owner. -
Category 1 Reserved Names: To prevent confusion with local DNS and networking standards, certain words are permanently blacklisted. Names like
localhost,test,invalid, orexampletrigger theReservedNameerror. -
Category 2 Infrastructure Names: Kinetic reserves specific names for protocol infrastructure and internal tooling. Trying to register
seed,explorer,docs, orapiwill fail. This triggers theInfrastructureNameerror. These are locked to prevent squatters from holding network infrastructure hostage. -
TLD Enforcement: If the network enforces a specific top-level domain for all registrations (such as
.kin), it checks this first. Submitting a name without it yieldsInvalidTLD.
4. Sled Storage Error Mapping
-> See: kinetic-core/src/error/storage.rs — Lines 13 to 24
Kinetic uses Sled, an embedded B-tree database, to persist state to the local disk. The storage error module acts as a translation layer. It maps Sled’s internal panics and errors into clean, structured Kinetic errors.
-
Lock Contention Management: Sled is strictly a single-writer database. It requires exclusive lock access to its database files. If a user accidentally runs
kinetic starttwice in the same terminal, it fails. The second instance will be blocked by the operating system file lock. This triggersDatabaseLocked(KIN-STO-001). This is a fatal condition that immediately kills the second process. It is the most critical error in the storage module. -
Structural Corruption Detection: If the machine loses power abruptly and the Sled write-ahead log becomes unreadable, it corrupts. Or, if the B-tree pointers become mangled, the database detects this during the startup integrity check. It returns
Corruption. This forces the node operator to intervene manually, possibly wiping the data folder. -
Routine Operational Failures: If a standard GET, PUT, or DELETE operation fails due to transient disk issues, it yields an error. The engine yields
OperationFailed. These are generally transient and safe to retry.
Key Pieces
The GovernanceError Enum Architecture
-> See: kinetic-core/src/error/governance.rs — Lines 23 to 57
This enumeration defines the entirety of the KIN-GOV-NNN taxonomy.
Each variant has specific mappings for standard trait methods.
MissingRootKey(KIN-GOV-001): This is mapped toSeverity::Critical. Theuser_message()clearly instructs the operator that theROOT_PUBLIC_KEY_HEXvariable is missing. It emphasizes that this is a fatal configuration error.GovernanceDisabled(KIN-GOV-002): This is mapped toSeverity::Warning. It informs the client that their request was rejected due to local node configuration. The node is operating in a permissionless state.KeyLengthMismatch(KIN-GOV-003): This is mapped toSeverity::Error. This indicates a cryptographic malformation.StaleProposal(KIN-GOV-004): This is mapped toSeverity::Info. Theis_retryable()method returnsfalsebecause an old proposal will never become valid.TimelockNotExpired(KIN-GOV-005): This is mapped toSeverity::Info. Crucially,is_retryable()returnstruefor this variant. A client simply needs to wait for the timelock window to pass and try broadcasting the execution again.InsufficientSignatures(KIN-GOV-016): This is mapped toSeverity::Warning. This is alsois_retryable() == true, because the proposal might gather more signatures in the future.- Note on Skipped Codes:
KIN-GOV-010,011, and012are intentionally skipped. This is to allow for future expansion in the stable registry.
The IdentityError Enum Architecture
-> See: kinetic-core/src/error/identity.rs — Lines 13 to 33
This enumeration defines the KIN-IDN-NNN taxonomy.
It has some unique trait implementations compared to the others.
- Manual
PartialEqImplementation: -> SeeRUST_CONCEPTS.mdfor whyIdentityErrorimplementsPartialEqmanually to handlestd::io::Error. Io(KIN-IDN-001): This is mapped toSeverity::Error. This is an unavoidable reality of disk-based identity files.CorruptedIdentityFile(KIN-IDN-002): This is mapped toSeverity::Error. Theuser_message()warns that the file cannot be used.DecryptionFailed(KIN-IDN-005): This is mapped toSeverity::Error. Theuser_message()clearly states that either the password is incorrect or the payload is mangled.InvalidSeedPhrase(KIN-IDN-004): Interestingly, this is mapped toSeverity::Warning. This is because providing a bad seed phrase in a CLI recovery command is usually user error. It is not a systemic failure of the node itself.- Retry Logic:
Every single variant in
IdentityErrorreturnsfalseforis_retryable(). Identity failures require manual intervention. Automated polling will not fix a corrupted file.
The NamesError Enum Architecture
-> See: kinetic-core/src/error/names.rs — Lines 15 to 44
This enumeration defines the KIN-NAM-NNN taxonomy.
It is purely focused on input validation.
- Trait Derivations:
This enum cleanly derives
Error,Debug,PartialEq,Eq, andClone. - Severity Mapping:
The
severity()method returnsSeverity::Warningfor all variants. This is a specific design decision. A user submitting a bad name is a validation failure, not a node health crisis. It warrants a warning in the logs, not an alert. - Retry Logic:
The
is_retryable()method unconditionally returnsfalse. If a name violates the RFC LDH rule once, it will violate it forever. - User Messages:
The
user_message()implementations are highly descriptive. For example,InvalidCharacterexplicitly lists the allowed subset. “Only lowercase letters, digits, and internal hyphens are allowed.”
The StorageError Enum Architecture
-> See: kinetic-core/src/error/storage.rs — Lines 13 to 24
This enumeration defines the KIN-STO-NNN taxonomy.
It is a bridge between third-party crates and Kinetic internal rules.
DatabaseLocked(KIN-STO-001): This is the only storage error mapped toSeverity::Critical. Theuser_message()clearly explains that another instance of the Kinetic daemon is already running.Corruption(KIN-STO-002): This is mapped toSeverity::Error. Theuser_message()hints that the local database may need to be reset.- Retry Logic:
The
is_retryable()method uses amatches!macro. It returnstrueonly if the error isOperationFailed. Lock contention and corruption are permanent dead ends. These require human intervention to fix.
How This Connects to the Rest of Kinetic
FORWARD DEPENDENCY: kinetic-storage
The StorageError enum is defined in the kinetic-core crate.
However, it is actually instantiated and returned by the database wrapper implementations.
These implementations live inside the kinetic-storage crate.
The core crate defines the abstract interface, and the storage crate fulfills it.
This inversion of dependency keeps the core clean.
CROSS-CRATE: kinetic-daemon
The kinetic-daemon crate’s boot sequence heavily relies on IdentityError and StorageError.
If the daemon encounters DatabaseLocked during boot, it halts.
If the daemon encounters MissingRootKey during governance initialization, it halts.
The daemon will invoke a hard std::process::exit(1).
These errors dictate the survival of the node process.
CROSS-CRATE: kinetic-rpc
When a wallet client submits a name registration via the JSON-RPC interface, it is verified.
The RPC server will invoke is_valid_apex_name.
If that function returns a NamesError, the RPC server intercepts it.
It extracts the user_message(), and serializes it into a JSON-RPC error response.
This ensures the wallet UI displays a clean, human-readable reason for the rejection.
FORWARD DEPENDENCY: Governance Execution Engines
The actual business logic that yields GovernanceError variants lives in the specialized execution engines.
These are the sovereign, council, and permissionless modules.
They implement the traits defined in core.
Quick Reference
- KIN-GOV-001:
MissingRootKey.- Severity: Critical.
- Action: The node cannot initialize governance without the founder root.
- KIN-GOV-003:
KeyLengthMismatch.- Severity: Error.
- Action: Ensure the key byte slice is exactly 1,952 bytes (ML-DSA-65).
- KIN-GOV-004:
StaleProposal.- Severity: Info.
- Action: The proposal is too old. Non-retryable.
- KIN-GOV-005:
TimelockNotExpired.- Severity: Info.
- Action: The waiting period is active. Retryable later.
- KIN-GOV-016:
InsufficientSignatures.- Severity: Warning.
- Action: Proposal lacks quorum. Retryable later.
- KIN-IDN-001:
Io.- Severity: Error.
- Action: Check filesystem permissions on the identity key directory.
- KIN-IDN-002:
CorruptedIdentityFile.- Severity: Error.
- Action: The ML-DSA-65 key payload is structurally invalid.
- KIN-IDN-004:
InvalidSeedPhrase.- Severity: Warning.
- Action: The BIP-39 mnemonic failed dictionary or checksum validation.
- KIN-IDN-005:
DecryptionFailed.- Severity: Error.
- Action: Incorrect password or failed MAC check.
- KIN-NAM-003:
InvalidCharacter.- Severity: Warning.
- Action: Ensure strict compliance with the RFC 5891 LDH rule.
- KIN-NAM-007:
NotAnApexName.- Severity: Warning.
- Action: Subnames cannot be registered directly on the global network.
- KIN-STO-001:
DatabaseLocked.- Severity: Critical.
- Action: Kill any ghost daemon processes competing for the Sled file lock.
- KIN-STO-002:
Corruption.- Severity: Error.
- Action: The Sled write-ahead log is mangled. Requires manual database wipe.
Open Questions / Things to Revisit
- Identity Key Format Flexibility:
Currently,
IdentityError::CorruptedIdentityFileexpects a very specific and rigid ML-DSA-65 format length. If Kinetic ever expands to support hardware security modules (HSMs), this must change. If we support different quantum-resistant signature schemes in the future, it must also change. The corruption logic will need to parse version headers rather than relying on raw byte length checks. - Name TLD Hardcoding:
The
InvalidTLDerror implies a hardcoded list of allowed TLDs (most likely just.kin). Should this list be adjustable via on-chain governance in the future? If so, the validator needs dynamic state access, not just static regex checks. - Sled Recovery Tooling:
StorageError::Corruptionis a dead end right now. Could we implement a standalone recovery tool? Or an auto-compaction mechanism that attempts to salvage key-value pairs from a corrupted Sled log? This would be better than forcing the user to wipe their node state. - Manual
PartialEqOverhead: We should ensure manual equality checking forstd::io::Errordoesn’t lead to false positives if two distinct IO errors happen to share the same.kind(). - Skipped Error Codes:
The governance module intentionally skips
KIN-GOV-010,KIN-GOV-011, andKIN-GOV-012. We should ensure that when new features are added, developers know these specific codes are reserved. They should be documented elsewhere to prevent collisions. These skipped blocks might suggest that features were removed or planned and never finished.