Complete Guide to Transaction Error Codes in Claude‑Obsidian
Claude‑Obsidian defines 23 specific string error codes across four exception classes—TransactionError, TransactionValidationError, TransactionConflict, and TransactionRecoveryError—to identify exact failure points ranging from invalid file paths to unsafe rollback conditions.
The transaction system in AgriciDaniel/claude-obsidian enforces strict safety guarantees when modifying Obsidian vaults. Located in claude_obsidian/transaction.py, the implementation raises granular transaction error codes that allow callers to distinguish between validation failures, runtime conflicts, and recovery errors without parsing ambiguous log messages.
Exception Hierarchy and Exit Codes
All transaction failures in claude-obsidian inherit from a base exception class mapped to specific process exit codes.
TransactionError serves as the abstract base for all transaction-related failures and returns exit code 1.
TransactionValidationError signals pre-condition violations before any vault modification occurs and returns exit code 2. This covers path validation, identity checks, and platform compatibility.
TransactionConflict indicates that a file changed while being inspected and returns exit code 75 (tempfail). This is raised in claude_obsidian/transaction.py when _safe_file_state detects a race condition between two stat calls (lines 100–106).
TransactionRecoveryError indicates that a transaction rollback cannot be performed safely and returns exit code 3. This is raised when _confined_vault_unlink detects that a rollback target’s content or identity changed since it was recorded (lines 21–29).
Path Validation Error Codes
The system validates every write path through _normalize_vault_path and _assert_portable_write_path, emitting specific codes for each failure mode.
INVALID_WRITE_PATH: Raised when the path is empty, contains control characters, backslashes, or is absolute (lines 58–63).NONCANONICAL_WRITE_PATH: Raised when the path is not in normalized POSIX form (lines 70–73).NONCANONICAL_UNICODE_PATH: Raised when the path is not NFC-normalized Unicode (lines 75–77).WRITE_PATH_TOO_LONG: Raised when the UTF-8 byte length exceeds the portable limit (lines 80–84).UNPORTABLE_WRITE_PATH: Raised when the path contains characters unsafe on portable filesystems (:<>|?*"), ends with a dot or space, or matches a reserved device name (lines 96–105).SYMLINK_WRITE_PATH: Raised by_assert_portable_write_pathwhen a write would traverse a symlink or junction (lines 112–115).
Vault directory constraints trigger additional validation codes:
CASEFOLD_PATH_ALIAS: Raised by_assert_no_portable_vault_leaf_alias_atwhen a sibling entry aliases the target when case-folded (lines 86–99).VAULT_DIRECTORY_LIMIT: Raised when a directory contains more thanMAX_PORTABLE_SIBLING_ENTRIESentries (lines 78–83).INVALID_VAULT_ROOT_NAME: Raised when the vault root name violates NFC, length, or control-character constraints (lines 64–74).
Operation and Identity Error Codes
Transaction metadata and vault identity verification use distinct error codes to signal contract violations.
INVALID_OPERATION_ID: Raised bysafe_operation_idwhen the operation ID is missing or contains unsafe characters (lines 38–49).UNSAFE_VAULT_IDENTITY: Raised by_vault_object_identitywhen the system cannot reliably pin a vault directory (lines 50–52).VAULT_NOT_DIRECTORY: Raised when the vault path exists but is not a directory (lines 55–58).VAULT_IDENTITY_CHANGED: Raised when the vault appeared or disappeared while its identity was being read (lines 63–66).UNSAFE_VAULT_PATH: General code for any situation where a path cannot be safely inspected due to symlinks, non-directory parents, or permission errors (e.g.,_safe_vault_pathlines 31–34).
File Size and Content Error Codes
Read operations and transaction size limits emit specific codes to prevent unbounded memory consumption.
INVALID_READ_LIMIT: Raised by_read_vault_regularwhen thelimitargument is not a positive integer (lines 38–41).VAULT_FILE_MISSING: Raised when the requested vault file does not exist andmissing_ok=False(lines 62–66).VAULT_FILE_TOO_LARGE: Raised when a vault file exceeds the allowed read limit (lines 96–99).TRANSACTION_FILE_TOO_LARGE: Raised by_safe_file_statewhen a file size exceedsMAX_TRANSACTION_FILE_BYTESduring a transaction (lines 86–89).
Conflict and Recovery Error Codes
Runtime race conditions and rollback failures use dedicated exception types.
FILE_CHANGED_DURING_READ: ATransactionConflictraised by_safe_file_statewhen a file changes between twostatcalls while being read (lines 100–106).ROLLBACK_TARGET_CHANGED: ATransactionRecoveryErrorraised by_confined_vault_unlinkwhen the rollback target’s content, type, or identity changed since it was recorded (lines 21–29).
Platform and Runtime Error Codes
Platform compatibility and runtime environment issues are detected before transaction execution.
UNSUPPORTED_PLATFORM: Raised by_require_write_platformwhen the host platform lacks required directory-descriptor confinement, such as native Windows (lines 16–18).UNSAFE_RUNTIME_PATH: Raised by_safe_directorywhen runtime directory creation or inspection fails, such as when the system cannot create a safe parent directory (lines 84–96).UNSAFE_LOCK_PATH: Raised viaTransactionValidationErrorin lock-related functions like_require_lock_dirfd_supportwhen lock-directory handling fails (lines 66–73).
Handling Transaction Errors in Python
Client code should catch specific exception types to implement appropriate retry or cleanup logic. All error codes are accessible via the .code attribute on exception instances.
from claude_obsidian.transaction import (
TransactionValidationError,
TransactionConflict,
TransactionRecoveryError
)
def safe_vault_write(operation_id, path, content):
try:
# Attempt transaction
pass
except TransactionValidationError as e:
# Handle pre-condition failures (exit code 2)
if e.code == "INVALID_WRITE_PATH":
print(f"Path validation failed: {e}")
elif e.code == "UNSUPPORTED_PLATFORM":
print("Platform lacks required confinement support")
raise
except TransactionConflict as e:
# Handle race conditions (exit code 75)
if e.code == "FILE_CHANGED_DURING_READ":
print("File modified during inspection; retry suggested")
raise
except TransactionRecoveryError as e:
# Handle rollback failures (exit code 3)
if e.code == "ROLLBACK_TARGET_CHANGED":
print("Rollback target modified; manual intervention required")
raise
The test suite in tests/test_transaction.py exercises each error condition to ensure codes are emitted correctly, while tests/test_vault_ops.py and tests/test_windows_compat.py verify platform-specific behavior.
Summary
- Four exception classes handle all transaction failures:
TransactionError(base),TransactionValidationError(exit code 2),TransactionConflict(exit code 75), andTransactionRecoveryError(exit code 3). - 23 string error codes provide granular failure identification, ranging from
INVALID_OPERATION_IDtoROLLBACK_TARGET_CHANGED. - Validation errors dominate the catalog, covering path normalization (
NONCANONICAL_WRITE_PATH), Unicode safety (NONCANONICAL_UNICODE_PATH), and vault identity (UNSAFE_VAULT_IDENTITY). - Conflict detection uses
FILE_CHANGED_DURING_READto signal race conditions during file inspection. - Platform safety is enforced via
UNSUPPORTED_PLATFORMfor environments lacking directory-descriptor confinement.
Frequently Asked Questions
What is the difference between TransactionValidationError and TransactionConflict?
TransactionValidationError (exit code 2) is raised before any filesystem modifications occur, covering issues like invalid paths or unsupported platforms. TransactionConflict (exit code 75) is raised during active file inspection when _safe_file_state detects that a file changed between consecutive stat calls, indicating a concurrent modification.
Which error code indicates a file changed during reading?
The FILE_CHANGED_DURING_READ code is raised as a TransactionConflict by the _safe_file_state function in claude_obsidian/transaction.py (lines 100–106) when the system detects a race condition during file inspection.
How do I handle platform-specific errors on Windows?
Catch TransactionValidationError with code UNSUPPORTED_PLATFORM, which is raised by _require_write_platform (lines 16–18) when the host lacks directory-descriptor confinement. Native Windows without WSL typically triggers this code, requiring you to implement alternative safety mechanisms or abort the transaction.
What exit code is returned for rollback failures?
TransactionRecoveryError returns exit code 3 when a rollback cannot be performed safely. The specific ROLLBACK_TARGET_CHANGED code indicates that the target file’s content, type, or identity changed since the transaction recorded its state, making automatic recovery impossible.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →