rustkmer 0.5.2

High-performance k-mer counting tool in Rust
Documentation
# Exception Hierarchy

This page documents the complete exception hierarchy used by the rustkmer Python API.

## Base Exception

### `RustKmerError`

Base exception for all rustkmer errors.

All rustkmer-specific exceptions inherit from this class, allowing users to catch all rustkmer errors with a single except clause while still enabling fine-grained error handling with specific exception types.

```python
try:
    db = PyDatabase("nonexistent.rkdb", LoadMode.Preload)
fuzzy = PyFuzzyQuery(db)
except RustKmerError as e:
    print(f"rustkmer error occurred: {e}")
```

## Database Errors

Database errors inherit from `RustKmerError` and handle issues related to database file operations.

### `DatabaseError`

Base class for all database-related errors.

```python
try:
    db = PyDatabase("invalid.rkdb", LoadMode.Preload)
fuzzy = PyFuzzyQuery(db)
except DatabaseError as e:
    print(f"Database error: {e}")
```

### `DatabaseNotFoundError`

Raised when a database file cannot be found at the specified path.

**Attributes:**
- `path`: The path that was attempted to be accessed

```python
try:
    db = PyDatabase("/nonexistent/path/database.rkdb", LoadMode.Preload)
fuzzy = PyFuzzyQuery(db)
except DatabaseNotFoundError as e:
    print(f"Database not found at: {e.path}")
    print(f"Error: {e}")
```

### `InvalidDatabaseError`

Raised when a file exists but is not a valid rustkmer database.

**Attributes:**
- `path`: The path to the invalid database file
- `reason`: Description of why the file is considered invalid

```python
try:
    db = PyDatabase("/path/to/wrong_format.txt", LoadMode.Preload)
fuzzy = PyFuzzyQuery(db)
except InvalidDatabaseError as e:
    print(f"Invalid database: {e.reason}")
    print(f"File path: {e.path}")
```

### `DatabaseCorruptedError`

Raised when a database file appears to be corrupted or unreadable.

**Attributes:**
- `path`: The path to the corrupted database file

```python
try:
    db = PyDatabase("/path/to/corrupted.rkdb", LoadMode.Preload)
fuzzy = PyFuzzyQuery(db)
except DatabaseCorruptedError as e:
    print(f"Database corrupted: {e.path}")
    # Try to recover or use backup
```

## Query Errors

Query errors inherit from `RustKmerError` and handle issues related to database query operations.

### `QueryError`

Base class for all query-related errors.

```python
try:
    result = db.query_exact("INVALID")
except QueryError as e:
    print(f"Query failed: {e}")
```

### `InvalidKmerError`

Raised when an invalid k-mer sequence is provided.

**Attributes:**
- `kmer`: The invalid k-mer sequence
- `reason`: Description of why the k-mer is invalid

```python
try:
    result = db.query_exact("ATXG")  # Invalid character X
except InvalidKmerError as e:
    print(f"Invalid k-mer: {e.kmer}")
    print(f"Reason: {e.reason}")
```

### `KmerLengthError`

Raised when k-mer length doesn't match database k-mer size.

**Attributes:**
- `expected_length`: The correct k-mer length for the database
- `actual_length`: The length of the provided k-mer

```python
try:
    result = db.query_exact("ATCG")  # Too short for k=31 database
except KmerLengthError as e:
    print(f"Expected length: {e.expected_length}")
    print(f"Actual length: {e.actual_length}")
    print(f"Invalid k-mer: {e.kmer}")
```

## Fuzzy Query Errors

Fuzzy query errors inherit from `QueryError` and handle issues specific to fuzzy query operations.

### `FuzzyQueryError`

Base exception for fuzzy query operations.

```python
try:
    result = fuzzy.query_fuzzy("ATCG", mutations=10)  # Too high
except FuzzyQueryError as e:
    print(f"Fuzzy query error: {e}")
```

### `InvalidMutationToleranceError`

Raised when mutation tolerance is out of valid range.

```python
try:
    result = fuzzy.query_fuzzy("ATCG", mutations=10)  # Too high
except InvalidMutationToleranceError as e:
    print("Mutation tolerance too high")
    print("Use a smaller value (0-5)")
```

### `InvalidPositionMutationError`

Raised when position-mutations parameter has invalid format or values.

**Attributes:**
- `position_config`: The invalid position mutation configuration string

```python
try:
    result = fuzzy.query_fuzzy("ATCG", position_mutations="invalid")
except InvalidPositionMutationError as e:
    print(f"Invalid format: {e.position_config}")
    print("Use format like '3,4:1' or '2-5:2'")
```

**Valid position-mutations formats:**
- `"3:1"` - Position 3 with max 1 mutation
- `"3,4,5:2"` - Positions 3,4,5 with max 2 mutations total
- `"4-7:1"` - Positions 4,5,6,7 with max 1 mutation
- `"3,4:1;6,7:2"` - Multiple independent groups

### `CombinatorialExplosionError`

Raised when fuzzy query would generate too many variants.

```python
try:
    result = fuzzy.query_fuzzy("ATCGATCGATCG", mutations=5)
except CombinatorialExplosionError as e:
    print("Too many variants would be generated")
    # Try reducing mutations or using max_variants parameter
    result = fuzzy.query_fuzzy("ATCGATCGATCG", mutations=3, max_variants=1000)
```

### `BatchQueryError`

Raised when batch fuzzy query encounters issues.

```python
try:
    results = db.fuzzy_query_batch(["ATCG", "GCTA", "INVALID"])
except BatchQueryError as e:
    print("Batch query failed")
    # Process queries individually to identify the problem
    for kmer in ["ATCG", "GCTA", "INVALID"]:
        try:
            result = fuzzy.query_fuzzy(kmer)
        except FuzzyQueryError as query_error:
            print(f"Query {kmer} failed: {query_error}")
```


### `ConfigurationError`

Raised when there's a configuration issue with the rustkmer package.

```python
try:
    db = PyDatabase("database.rkdb")
fuzzy = PyFuzzyQuery(db)  # May trigger config validation
except ConfigurationError as e:
    print(f"Configuration issue: {e}")
    print("Check rustkmer installation and environment")
```

## Error Handling Best Practices

### 1. Specific Error Handling

```python
# Handle specific errors appropriately
try:
    db = PyDatabase("database.rkdb", LoadMode.Preload)
fuzzy = PyFuzzyQuery(db)
except DatabaseNotFoundError:
    print("Database not found. Check the file path.")
    sys.exit(1)
except InvalidDatabaseError:
    print("Invalid database format. The file may be corrupted.")
    sys.exit(1)
```

### 2. General Error Handling

```python
# Catch all rustkmer errors
try:
    result = fuzzy.query_fuzzy("ATCG", mutations=2)
except RustKmerError as e:
    print(f"rustkmer error: {e}")
    # Handle or log the error appropriately
```

### 3. Error Recovery Strategies

```python
def safe_query_with_retry(db, kmer, max_retries=3):
    """Query with retry logic for common errors."""
    for attempt in range(max_retries):
        try:
            return db.query_exact(kmer)
        except DatabaseNotFoundError:
            # File doesn't exist, no point retrying
            raise
        except QueryError as e:
            if attempt == max_retries - 1:
                raise
            print(f"Query attempt {attempt + 1} failed, retrying...")
            time.sleep(1)  # Wait before retry
    return None
```

## Migration Guide

### From Previous Versions

If you're upgrading from a version of rustkmer before 1.0:

1. **New Exception Hierarchy**: The exception hierarchy has been restructured for better organization.
2. **Additional Attributes**: Many exceptions now provide additional helpful attributes.
3. **Better Error Messages**: Error messages are more descriptive and actionable.

### Breaking Changes

- `DatabaseError` no longer inherits from `FileNotFoundError` directly
- `InvalidKmerError` no longer inherits from `ValueError` directly
- New position mutation related exceptions have been added

### Updated Imports

```python
# Old imports (pre-1.0)
from rustkmer.exceptions import DatabaseError, QueryError

# New imports (1.0+)
from rustkmer.exceptions import (
    DatabaseError, QueryError, InvalidKmerError,
    DatabaseNotFoundError, InvalidDatabaseError,
    FuzzyQueryError, InvalidMutationToleranceError,
    ConfigurationError
)
```