Skip to main content

Appendix III: Error Codes and Troubleshooting

Overview

This chapter provides comprehensive documentation for all error codes, exception types, and troubleshooting procedures in Vektagraf. Understanding error patterns and resolution strategies is essential for building robust applications and maintaining system reliability.

Learning Objectives

  • Understand all error codes and their meanings
  • Master systematic troubleshooting procedures
  • Learn error prevention strategies and best practices
  • Explore diagnostic tools and monitoring techniques
  • Understand performance troubleshooting and optimization

Prerequisites

  • Basic understanding of Vektagraf architecture
  • Familiarity with exception handling in Dart
  • Knowledge of database operations and transactions

Error Classification System

Vektagraf uses a hierarchical error classification system with specific error codes and categories:

Error Code Format

VKG-[CATEGORY]-[SUBCATEGORY]-[NUMBER]

Examples:
VKG-DB-001    - Database connection error
VKG-TX-002    - Transaction conflict error
VKG-SEC-003   - Authentication failure
VKG-VEC-004   - Vector dimension mismatch

Error Categories

Category Code Description
Database DB Core database operations
Transaction TX Transaction and concurrency
Security SEC Authentication and authorization
Vector VEC Vector operations and search
Graph GRP Graph operations and traversal
Schema SCH Schema parsing and validation
Network NET Network and transport layer
Storage STO Storage engine operations
Configuration CFG Configuration and setup
Multi-Tenant MT Multi-tenancy operations

Core Database Errors

VKG-DB-001: Database Connection Failed

Description: Failed to establish connection to database

Common Causes:

  • Invalid database path or URL
  • Insufficient permissions
  • Database file corruption
  • Network connectivity issues (hosted mode)

Resolution Steps:

try {
  await database.open('/path/to/database.vektagraf');
} on DatabaseException catch (e) {
  if (e.message.contains('connection failed')) {
    // Check file permissions
    final file = File('/path/to/database.vektagraf');
    if (!await file.exists()) {
      print('Database file does not exist, creating new database');
      // Create parent directories if needed
      await file.parent.create(recursive: true);
      await database.open('/path/to/database.vektagraf');
    } else {
      // Check permissions
      try {
        await file.readAsBytes();
        print('File is readable, checking for corruption');
        // Attempt database repair
        await repairDatabase('/path/to/database.vektagraf');
      } catch (permissionError) {
        print('Permission denied: ${permissionError}');
        // Fix permissions or use alternative path
      }
    }
  }
}

Prevention:

  • Validate database paths before opening
  • Ensure proper file permissions
  • Use connection pooling for hosted mode
  • Implement health checks

VKG-DB-002: Database Already Open

Description: Attempt to open database that is already open

Resolution:

if (!database.isOpen) {
  await database.open(databasePath);
} else {
  print('Database is already open');
}

VKG-DB-003: Database Not Open

Description: Operation attempted on closed database

Resolution:

Future<void> ensureDatabaseOpen() async {
  if (!database.isOpen) {
    await database.open(databasePath);
  }
}

// Use before operations
await ensureDatabaseOpen();
final users = await database.objects<User>();

VKG-DB-004: Invalid Object Type

Description: Object type not defined in schema or invalid

Resolution:

try {
  final users = await database.objects<User>();
} on SchemaException catch (e) {
  print('Schema error: ${e.message}');
  // Check if User is defined in schema
  final schema = await loadSchema();
  if (!schema.models.containsKey('User')) {
    print('User model not found in schema');
    // Add User model to schema or use correct type
  }
}

Transaction Errors

VKG-TX-001: Transaction Already Active

Description: Attempt to start transaction when one is already active

Resolution:

// Check transaction state before starting
if (!transaction.isActive) {
  await database.transaction((txn) async {
    // Transaction operations
  });
} else {
  print('Transaction already active');
}

VKG-TX-002: Concurrency Conflict

Description: Optimistic locking failure due to concurrent modifications

Common Causes:

  • Multiple clients modifying same object
  • Stale revision numbers
  • Long-running transactions

Resolution:

Future<void> handleConcurrencyConflict<T>(
  VektagrafId objectId,
  T updatedObject,
  int maxRetries = 3,
) async {
  int attempts = 0;
  
  while (attempts < maxRetries) {
    try {
      await database.transaction((txn) async {
        final current = await txn.getById<T>(objectId);
        if (current != null) {
          // Get current revision
          final currentRevision = getCurrentRevision(current);
          await txn.update(objectId, updatedObject, currentRevision);
        }
      });
      return; // Success
    } on ConcurrencyConflictException catch (e) {
      attempts++;
      if (attempts >= maxRetries) {
        print('Max retries exceeded: ${e.message}');
        rethrow;
      }
      
      // Exponential backoff
      await Future.delayed(Duration(milliseconds: 100 * (1 << attempts)));
      
      // Refresh object state
      updatedObject = await refreshObjectState(objectId, updatedObject);
    }
  }
}

VKG-TX-003: Transaction Timeout

Description: Transaction exceeded maximum allowed duration

Resolution:

// Use shorter transactions
await database.transaction((txn) async {
  // Break large operations into smaller chunks
  final batchSize = 100;
  for (int i = 0; i < objects.length; i += batchSize) {
    final batch = objects.skip(i).take(batchSize);
    await txn.saveAll(batch);
    
    // Commit periodically for long operations
    if (i > 0 && i % 1000 == 0) {
      await txn.commit();
      // Start new transaction for next batch
    }
  }
});

VKG-TX-004: Transaction Rollback Failed

Description: Failed to rollback transaction properly

Resolution:

try {
  await database.transaction((txn) async {
    // Operations that might fail
    throw Exception('Simulated failure');
  });
} catch (e) {
  print('Transaction failed and was rolled back: $e');
  // Check database consistency
  await validateDatabaseConsistency();
}

Security Errors

VKG-SEC-001: Authentication Failed

Description: Invalid credentials or authentication failure

Resolution:

try {
  final client = VektagrafClient(VektagrafClientConfig(
    username: 'user',
    password: 'password',
  ));
  await client.open('https://api.example.com');
} on VektagrafAuthenticationException catch (e) {
  print('Authentication failed: ${e.message}');
  
  // Check credentials
  if (e.message.contains('invalid credentials')) {
    // Prompt for new credentials
    final newCredentials = await promptForCredentials();
    // Retry with new credentials
  } else if (e.message.contains('account locked')) {
    // Handle account lockout
    await handleAccountLockout();
  }
}

VKG-SEC-002: Authorization Failed

Description: Insufficient permissions for requested operation

Resolution:

try {
  await database.objects<User>().save(newUser);
} on VektagrafAuthorizationException catch (e) {
  print('Authorization failed: ${e.message}');
  
  // Check user permissions
  final permissions = await getUserPermissions();
  if (!permissions.contains('user:create')) {
    print('User lacks create permission');
    // Request permission elevation or use different approach
  }
}

VKG-SEC-003: Rate Limit Exceeded

Description: Too many requests within time window

Resolution:

Future<T> executeWithRateLimit<T>(
  Future<T> Function() operation,
  {int maxRetries = 3}
) async {
  int attempts = 0;
  
  while (attempts < maxRetries) {
    try {
      return await operation();
    } on VektagrafRateLimitException catch (e) {
      attempts++;
      if (attempts >= maxRetries) rethrow;
      
      // Extract retry-after header if available
      final retryAfter = extractRetryAfter(e.message) ?? 
                        Duration(seconds: 1 << attempts);
      
      print('Rate limited, waiting ${retryAfter.inSeconds}s');
      await Future.delayed(retryAfter);
    }
  }
  
  throw StateError('Max retries exceeded');
}

VKG-SEC-004: Tenant Limit Exceeded

Description: Tenant has exceeded configured limits

Resolution:

try {
  await tenantMiddleware.executeWithLimits(
    tenantId,
    userId,
    'create',
    () => database.objects<Document>().save(document),
  );
} on TenantLimitException catch (e) {
  print('Tenant limit exceeded: ${e.message}');
  
  switch (e.limitType) {
    case 'storage':
      await handleStorageLimit(e.tenantId);
      break;
    case 'rate_limit':
      await handleRateLimit(e.tenantId);
      break;
    case 'request_quota':
      await handleRequestQuota(e.tenantId);
      break;
  }
}

Future<void> handleStorageLimit(String tenantId) async {
  // Notify tenant of storage limit
  await notifyTenantOfLimit(tenantId, 'storage');
  
  // Suggest cleanup or upgrade
  final usage = await getTenantStorageUsage(tenantId);
  print('Current usage: ${usage['currentBytes']} / ${usage['limitBytes']}');
  
  // Offer cleanup suggestions
  final suggestions = await getCleanupSuggestions(tenantId);
  for (final suggestion in suggestions) {
    print('Suggestion: ${suggestion}');
  }
}

Vector Search Errors

VKG-VEC-001: Dimension Mismatch

Description: Vector dimensions don't match vector space configuration

Resolution:

try {
  final vectorSpace = database.vectorSpace('embeddings', 512);
  await vectorSpace.addVector(vector); // Wrong dimensions
} on ArgumentError catch (e) {
  if (e.message.contains('dimension')) {
    print('Vector dimension mismatch: ${e.message}');
    
    // Check vector dimensions
    print('Vector dimensions: ${vector.length}');
    print('Expected dimensions: 512');
    
    // Resize vector if possible
    if (vector.length > 512) {
      vector = vector.take(512).toList(); // Truncate
    } else if (vector.length < 512) {
      vector = [...vector, ...List.filled(512 - vector.length, 0.0)]; // Pad
    }
    
    // Retry with corrected vector
    await vectorSpace.addVector(vector);
  }
}

VKG-VEC-002: Invalid Vector Data

Description: Vector contains invalid values (NaN, infinity)

Resolution:

List<double> sanitizeVector(List<double> vector) {
  return vector.map((value) {
    if (value.isNaN) return 0.0;
    if (value.isInfinite) return value.isNegative ? -1.0 : 1.0;
    return value;
  }).toList();
}

// Use before adding vectors
final sanitizedVector = sanitizeVector(originalVector);
await vectorSpace.addVector(sanitizedVector);

VKG-VEC-003: Vector Space Not Found

Description: Attempting to access non-existent vector space

Resolution:

VektagrafVectorSpace getOrCreateVectorSpace(String name, int dimensions) {
  try {
    return database.vectorSpace(name, dimensions);
  } catch (e) {
    print('Vector space $name not found, creating...');
    // Vector spaces are created automatically when accessed
    return database.vectorSpace(name, dimensions);
  }
}

Graph Operation Errors

VKG-GRP-001: Node Not Found

Description: Graph node does not exist

Resolution:

try {
  final node = await database.graph.getNode(nodeId);
  if (node == null) {
    print('Node $nodeId not found');
    // Create node if needed
    final newNodeId = await database.graph.addNode({
      'type': 'User',
      'name': 'Default User',
    });
    return newNodeId;
  }
} on VektagrafNotFoundException catch (e) {
  print('Node not found: ${e.message}');
  // Handle missing node
}

VKG-GRP-002: Circular Reference

Description: Graph operation would create circular reference

Resolution:

Future<bool> wouldCreateCycle(VektagrafId fromId, VektagrafId toId) async {
  // Check if adding edge from->to would create cycle
  final path = await database.graph.shortestPath(toId, fromId);
  return path != null; // If path exists, adding edge would create cycle
}

// Use before adding edges
if (!await wouldCreateCycle(fromId, toId)) {
  await database.graph.addEdge(fromId, toId);
} else {
  print('Cannot add edge: would create circular reference');
}

Schema Errors

VKG-SCH-001: Schema Parse Error

Description: Invalid JSON schema format

Resolution:

try {
  final parser = VektagrafSchemaParser();
  final schema = parser.parseFromString(schemaJson);
} on SchemaParseException catch (e) {
  print('Schema parse error: ${e.message}');
  if (e.field != null) print('Field: ${e.field}');
  if (e.model != null) print('Model: ${e.model}');
  
  // Validate JSON first
  try {
    jsonDecode(schemaJson);
  } catch (jsonError) {
    print('Invalid JSON: $jsonError');
    // Fix JSON syntax errors
  }
  
  // Check schema structure
  final json = jsonDecode(schemaJson) as Map<String, dynamic>;
  if (!json.containsKey('models')) {
    print('Schema missing required "models" section');
  }
}

VKG-SCH-002: Model Not Found

Description: Referenced model does not exist in schema

Resolution:

void validateModelReferences(VektagrafSchema schema) {
  for (final model in schema.models.values) {
    for (final field in model.relationshipFields) {
      final targetModel = field.relationshipConfig!.targetModel;
      if (!schema.models.containsKey(targetModel)) {
        print('Model ${model.name} references unknown model: $targetModel');
        // Add missing model or fix reference
      }
    }
  }
}

Network and Transport Errors

VKG-NET-001: Connection Timeout

Description: Network operation timed out

Resolution:

final client = VektagrafClient(VektagrafClientConfig(
  timeout: Duration(seconds: 60), // Increase timeout
  username: 'user',
  password: 'password',
));

// Implement retry with exponential backoff
Future<T> withRetry<T>(Future<T> Function() operation) async {
  int attempts = 0;
  const maxAttempts = 3;
  
  while (attempts < maxAttempts) {
    try {
      return await operation();
    } on VektagrafTimeoutException catch (e) {
      attempts++;
      if (attempts >= maxAttempts) rethrow;
      
      final delay = Duration(seconds: 1 << attempts);
      print('Timeout, retrying in ${delay.inSeconds}s...');
      await Future.delayed(delay);
    }
  }
  
  throw StateError('Max attempts exceeded');
}

VKG-NET-002: Service Unavailable

Description: Server is temporarily unavailable

Resolution:

try {
  await client.open('https://api.example.com');
} on VektagrafServiceUnavailableException catch (e) {
  print('Service unavailable: ${e.message}');
  
  // Check server status
  final status = await checkServerStatus();
  if (status.isMaintenanceMode) {
    print('Server in maintenance mode until ${status.maintenanceEnd}');
    // Wait or use fallback
  } else {
    // Try alternative endpoints
    for (final endpoint in alternativeEndpoints) {
      try {
        await client.open(endpoint);
        break;
      } catch (e) {
        print('Alternative endpoint failed: $endpoint');
      }
    }
  }
}

Performance Troubleshooting

Slow Query Performance

Symptoms:

  • Queries taking longer than expected
  • High CPU usage during queries
  • Memory usage spikes

Diagnostic Steps:

// Enable query profiling
final config = VektagrafConfig(
  enableQueryProfiling: true,
  profilingThreshold: Duration(milliseconds: 100),
);

// Monitor query performance
class QueryProfiler {
  final Map<String, List<Duration>> _queryTimes = {};
  
  Future<T> profileQuery<T>(
    String queryName,
    Future<T> Function() query,
  ) async {
    final stopwatch = Stopwatch()..start();
    
    try {
      final result = await query();
      return result;
    } finally {
      stopwatch.stop();
      _recordQueryTime(queryName, stopwatch.elapsed);
    }
  }
  
  void _recordQueryTime(String queryName, Duration duration) {
    _queryTimes.putIfAbsent(queryName, () => []).add(duration);
    
    // Log slow queries
    if (duration > Duration(milliseconds: 100)) {
      print('Slow query detected: $queryName took ${duration.inMilliseconds}ms');
    }
  }
  
  Map<String, QueryStats> getQueryStats() {
    return _queryTimes.map((name, times) {
      final avgTime = times.fold<int>(0, (sum, time) => sum + time.inMilliseconds) / times.length;
      final maxTime = times.fold<Duration>(Duration.zero, (max, time) => time > max ? time : max);
      
      return MapEntry(name, QueryStats(
        queryName: name,
        executionCount: times.length,
        averageTime: Duration(milliseconds: avgTime.round()),
        maxTime: maxTime,
      ));
    });
  }
}

class QueryStats {
  final String queryName;
  final int executionCount;
  final Duration averageTime;
  final Duration maxTime;
  
  QueryStats({
    required this.queryName,
    required this.executionCount,
    required this.averageTime,
    required this.maxTime,
  });
}

Optimization Strategies:

// 1. Add indexes for frequently queried fields
await database.createIndex('User', 'email'); // If supported

// 2. Use property-based queries instead of full scans
final users = await database.objects<User>()
  .whereProperty('isActive', true)  // Optimized
  .take(100);

// Instead of:
final allUsers = await database.objects<User>();
final activeUsers = allUsers.where((u) => u.isActive).take(100);

// 3. Batch operations
final batchSize = 100;
for (int i = 0; i < users.length; i += batchSize) {
  final batch = users.skip(i).take(batchSize);
  await database.transaction((txn) async {
    await txn.saveAll(batch);
  });
}

// 4. Use pagination for large result sets
Future<List<T>> getPaginatedResults<T>(
  VektagrafList<T> list,
  int page,
  int pageSize,
) async {
  return list.skip(page * pageSize).take(pageSize).toList();
}

Memory Usage Issues

Symptoms:

  • Out of memory errors
  • Gradual memory increase
  • Poor garbage collection performance

Diagnostic Steps:

class MemoryMonitor {
  Timer? _timer;
  final List<MemorySnapshot> _snapshots = [];
  
  void startMonitoring() {
    _timer = Timer.periodic(Duration(seconds: 30), (_) {
      _takeSnapshot();
    });
  }
  
  void stopMonitoring() {
    _timer?.cancel();
  }
  
  void _takeSnapshot() {
    // In a real implementation, you'd use platform-specific memory APIs
    final snapshot = MemorySnapshot(
      timestamp: DateTime.now(),
      heapUsage: _getHeapUsage(),
      objectCount: _getObjectCount(),
    );
    
    _snapshots.add(snapshot);
    
    // Keep only last 100 snapshots
    if (_snapshots.length > 100) {
      _snapshots.removeAt(0);
    }
    
    // Check for memory leaks
    if (_snapshots.length > 10) {
      final recent = _snapshots.takeLast(10);
      final trend = _calculateMemoryTrend(recent);
      
      if (trend > 0.1) { // 10% increase trend
        print('Potential memory leak detected');
        _analyzeMemoryUsage();
      }
    }
  }
  
  double _calculateMemoryTrend(Iterable<MemorySnapshot> snapshots) {
    if (snapshots.length < 2) return 0.0;
    
    final first = snapshots.first.heapUsage;
    final last = snapshots.last.heapUsage;
    
    return (last - first) / first;
  }
  
  void _analyzeMemoryUsage() {
    // Analyze memory usage patterns
    print('Memory usage analysis:');
    print('Current heap: ${_getHeapUsage()} bytes');
    print('Object count: ${_getObjectCount()}');
    
    // Suggest optimizations
    print('Optimization suggestions:');
    print('- Reduce cache size if memory constrained');
    print('- Use pagination for large result sets');
    print('- Clear unused object references');
  }
  
  int _getHeapUsage() {
    // Platform-specific implementation needed
    return 0;
  }
  
  int _getObjectCount() {
    // Platform-specific implementation needed
    return 0;
  }
}

class MemorySnapshot {
  final DateTime timestamp;
  final int heapUsage;
  final int objectCount;
  
  MemorySnapshot({
    required this.timestamp,
    required this.heapUsage,
    required this.objectCount,
  });
}

Memory Optimization:

// 1. Reduce cache size for memory-constrained environments
final config = VektagrafConfig(
  cacheSize: 100, // Reduce from default 1000
  maxMemoryBytes: 64 * 1024 * 1024, // 64MB limit
);

// 2. Use streaming for large datasets
Stream<User> streamUsers() async* {
  const batchSize = 100;
  int offset = 0;
  
  while (true) {
    final batch = await database.objects<User>()
      .skip(offset)
      .take(batchSize);
    
    if (batch.isEmpty) break;
    
    for (final user in batch) {
      yield user;
    }
    
    offset += batchSize;
  }
}

// 3. Clear references when done
void processUsers() async {
  var users = await database.objects<User>();
  
  // Process users
  for (final user in users) {
    await processUser(user);
  }
  
  // Clear reference to allow garbage collection
  users = null;
}
```## Syst
ematic Troubleshooting Procedures

### General Troubleshooting Workflow

```mermaid
flowchart TD
    A[Issue Reported] --> B[Gather Information]
    B --> C[Identify Error Category]
    C --> D[Check Common Causes]
    D --> E[Apply Resolution Steps]
    E --> F{Issue Resolved?}
    F -->|Yes| G[Document Solution]
    F -->|No| H[Escalate or Deep Dive]
    H --> I[Advanced Diagnostics]
    I --> J[Apply Advanced Solutions]
    J --> F
    G --> K[Monitor for Recurrence]

Information Gathering Checklist

When troubleshooting issues, collect the following information:

Environment Information:

class DiagnosticInfo {
  static Map<String, dynamic> gatherSystemInfo() {
    return {
      'platform': Platform.operatingSystem,
      'version': Platform.operatingSystemVersion,
      'dartVersion': Platform.version,
      'vektagrafVersion': getVektagrafVersion(),
      'timestamp': DateTime.now().toIso8601String(),
      'memoryUsage': _getMemoryUsage(),
      'diskSpace': _getDiskSpace(),
    };
  }
  
  static Map<String, dynamic> gatherDatabaseInfo(VektagrafDatabase database) {
    return {
      'isOpen': database.isOpen,
      'config': database.config?.toJson(),
      'connectionMode': database.isHosted ? 'hosted' : 'embedded',
      'activeTransactions': _getActiveTransactionCount(),
      'cacheStats': _getCacheStatistics(),
    };
  }
  
  static Map<String, dynamic> gatherErrorContext(Exception error) {
    return {
      'errorType': error.runtimeType.toString(),
      'message': error.toString(),
      'stackTrace': StackTrace.current.toString(),
      'timestamp': DateTime.now().toIso8601String(),
    };
  }
}

Configuration Validation:

class ConfigurationDiagnostics {
  static List<String> validateConfiguration(VektagrafConfig config) {
    final issues = <String>[];
    
    // Memory validation
    if (config.maxMemoryBytes < 64 * 1024 * 1024) {
      issues.add('Memory too low: ${config.maxMemoryBytes} bytes (minimum 64MB)');
    }
    
    // Cache validation
    if (config.cacheSize < 100) {
      issues.add('Cache size too small: ${config.cacheSize} (minimum 100)');
    }
    
    // Multi-tenancy validation
    if (config.isMultiTenantEnabled) {
      if (config.multiTenancy?.strictIsolation != true) {
        issues.add('Multi-tenancy enabled but strict isolation disabled');
      }
    }
    
    return issues;
  }
  
  static Map<String, dynamic> analyzePerformanceConfig(VektagrafConfig config) {
    final analysis = <String, dynamic>{};
    
    // Memory analysis
    final memoryMB = config.maxMemoryBytes / (1024 * 1024);
    analysis['memoryMB'] = memoryMB;
    analysis['memoryLevel'] = memoryMB < 128 ? 'low' : 
                             memoryMB < 512 ? 'medium' : 'high';
    
    // Cache analysis
    analysis['cacheSize'] = config.cacheSize;
    analysis['cacheLevel'] = config.cacheSize < 1000 ? 'small' :
                            config.cacheSize < 5000 ? 'medium' : 'large';
    
    // Durability analysis
    analysis['durabilityMode'] = config.syncMode.name;
    analysis['walEnabled'] = config.enableWAL;
    
    return analysis;
  }
}

Database Health Checks

class DatabaseHealthChecker {
  final VektagrafDatabase database;
  
  DatabaseHealthChecker(this.database);
  
  Future<HealthCheckResult> performHealthCheck() async {
    final results = <String, bool>{};
    final issues = <String>[];
    
    // Connection check
    try {
      results['connection'] = database.isOpen;
      if (!database.isOpen) {
        issues.add('Database connection is closed');
      }
    } catch (e) {
      results['connection'] = false;
      issues.add('Connection check failed: $e');
    }
    
    // Basic operation check
    try {
      await database.objects<TestObject>();
      results['basicOperations'] = true;
    } catch (e) {
      results['basicOperations'] = false;
      issues.add('Basic operations failed: $e');
    }
    
    // Transaction check
    try {
      await database.transaction((txn) async {
        // Simple transaction test
        return true;
      });
      results['transactions'] = true;
    } catch (e) {
      results['transactions'] = false;
      issues.add('Transaction test failed: $e');
    }
    
    // Vector space check
    try {
      database.vectorSpace('health_check', 128);
      results['vectorSpaces'] = true;
    } catch (e) {
      results['vectorSpaces'] = false;
      issues.add('Vector space check failed: $e');
    }
    
    // Graph operations check
    try {
      database.graph;
      results['graphOperations'] = true;
    } catch (e) {
      results['graphOperations'] = false;
      issues.add('Graph operations check failed: $e');
    }
    
    final overallHealth = results.values.every((result) => result);
    
    return HealthCheckResult(
      isHealthy: overallHealth,
      checks: results,
      issues: issues,
      timestamp: DateTime.now(),
    );
  }
  
  Future<PerformanceMetrics> gatherPerformanceMetrics() async {
    final stopwatch = Stopwatch();
    
    // Measure basic operations
    stopwatch.start();
    await database.objects<TestObject>();
    final objectsTime = stopwatch.elapsedMilliseconds;
    
    stopwatch.reset();
    await database.transaction((txn) async {
      return true;
    });
    final transactionTime = stopwatch.elapsedMilliseconds;
    
    stopwatch.reset();
    database.vectorSpace('perf_test', 128);
    final vectorSpaceTime = stopwatch.elapsedMilliseconds;
    
    return PerformanceMetrics(
      objectsOperationMs: objectsTime,
      transactionMs: transactionTime,
      vectorSpaceMs: vectorSpaceTime,
      timestamp: DateTime.now(),
    );
  }
}

class HealthCheckResult {
  final bool isHealthy;
  final Map<String, bool> checks;
  final List<String> issues;
  final DateTime timestamp;
  
  HealthCheckResult({
    required this.isHealthy,
    required this.checks,
    required this.issues,
    required this.timestamp,
  });
  
  @override
  String toString() {
    final buffer = StringBuffer();
    buffer.writeln('Health Check Result: ${isHealthy ? 'HEALTHY' : 'UNHEALTHY'}');
    buffer.writeln('Timestamp: $timestamp');
    buffer.writeln('Checks:');
    
    for (final entry in checks.entries) {
      final status = entry.value ? 'PASS' : 'FAIL';
      buffer.writeln('  ${entry.key}: $status');
    }
    
    if (issues.isNotEmpty) {
      buffer.writeln('Issues:');
      for (final issue in issues) {
        buffer.writeln('  - $issue');
      }
    }
    
    return buffer.toString();
  }
}

class PerformanceMetrics {
  final int objectsOperationMs;
  final int transactionMs;
  final int vectorSpaceMs;
  final DateTime timestamp;
  
  PerformanceMetrics({
    required this.objectsOperationMs,
    required this.transactionMs,
    required this.vectorSpaceMs,
    required this.timestamp,
  });
}

class TestObject {
  final String id;
  final String name;
  
  TestObject({required this.id, required this.name});
}

Automated Diagnostics

class AutomatedDiagnostics {
  static Future<DiagnosticReport> runFullDiagnostics(
    VektagrafDatabase database,
  ) async {
    final report = DiagnosticReport();
    
    // System information
    report.systemInfo = DiagnosticInfo.gatherSystemInfo();
    report.databaseInfo = DiagnosticInfo.gatherDatabaseInfo(database);
    
    // Configuration validation
    if (database.config != null) {
      report.configIssues = ConfigurationDiagnostics.validateConfiguration(database.config!);
      report.performanceAnalysis = ConfigurationDiagnostics.analyzePerformanceConfig(database.config!);
    }
    
    // Health checks
    final healthChecker = DatabaseHealthChecker(database);
    report.healthCheck = await healthChecker.performHealthCheck();
    report.performanceMetrics = await healthChecker.gatherPerformanceMetrics();
    
    // Resource usage
    report.resourceUsage = await _gatherResourceUsage();
    
    // Generate recommendations
    report.recommendations = _generateRecommendations(report);
    
    return report;
  }
  
  static Future<Map<String, dynamic>> _gatherResourceUsage() async {
    return {
      'memoryUsage': _getCurrentMemoryUsage(),
      'diskUsage': await _getDiskUsage(),
      'cpuUsage': _getCpuUsage(),
      'networkStats': await _getNetworkStats(),
    };
  }
  
  static List<String> _generateRecommendations(DiagnosticReport report) {
    final recommendations = <String>[];
    
    // Performance recommendations
    final perfAnalysis = report.performanceAnalysis;
    if (perfAnalysis['memoryLevel'] == 'low') {
      recommendations.add('Consider increasing maxMemoryBytes for better performance');
    }
    
    if (perfAnalysis['cacheLevel'] == 'small') {
      recommendations.add('Consider increasing cacheSize for better read performance');
    }
    
    // Health check recommendations
    if (!report.healthCheck.isHealthy) {
      recommendations.add('Address health check failures before production use');
    }
    
    // Configuration recommendations
    if (report.configIssues.isNotEmpty) {
      recommendations.add('Fix configuration issues: ${report.configIssues.join(', ')}');
    }
    
    return recommendations;
  }
  
  static int _getCurrentMemoryUsage() => 0; // Platform-specific implementation
  static Future<int> _getDiskUsage() async => 0; // Platform-specific implementation
  static double _getCpuUsage() => 0.0; // Platform-specific implementation
  static Future<Map<String, dynamic>> _getNetworkStats() async => {}; // Platform-specific implementation
}

class DiagnosticReport {
  Map<String, dynamic> systemInfo = {};
  Map<String, dynamic> databaseInfo = {};
  List<String> configIssues = [];
  Map<String, dynamic> performanceAnalysis = {};
  late HealthCheckResult healthCheck;
  late PerformanceMetrics performanceMetrics;
  Map<String, dynamic> resourceUsage = {};
  List<String> recommendations = [];
  
  @override
  String toString() {
    final buffer = StringBuffer();
    buffer.writeln('=== Vektagraf Diagnostic Report ===');
    buffer.writeln('Generated: ${DateTime.now()}');
    buffer.writeln();
    
    buffer.writeln('System Information:');
    systemInfo.forEach((key, value) {
      buffer.writeln('  $key: $value');
    });
    buffer.writeln();
    
    buffer.writeln('Database Information:');
    databaseInfo.forEach((key, value) {
      buffer.writeln('  $key: $value');
    });
    buffer.writeln();
    
    if (configIssues.isNotEmpty) {
      buffer.writeln('Configuration Issues:');
      for (final issue in configIssues) {
        buffer.writeln('  - $issue');
      }
      buffer.writeln();
    }
    
    buffer.writeln('Performance Analysis:');
    performanceAnalysis.forEach((key, value) {
      buffer.writeln('  $key: $value');
    });
    buffer.writeln();
    
    buffer.writeln(healthCheck.toString());
    buffer.writeln();
    
    buffer.writeln('Performance Metrics:');
    buffer.writeln('  Objects operation: ${performanceMetrics.objectsOperationMs}ms');
    buffer.writeln('  Transaction: ${performanceMetrics.transactionMs}ms');
    buffer.writeln('  Vector space: ${performanceMetrics.vectorSpaceMs}ms');
    buffer.writeln();
    
    if (recommendations.isNotEmpty) {
      buffer.writeln('Recommendations:');
      for (final recommendation in recommendations) {
        buffer.writeln('  - $recommendation');
      }
    }
    
    return buffer.toString();
  }
}

Error Prevention Strategies

Input Validation

class InputValidator {
  static void validateVectorDimensions(List<double> vector, int expectedDimensions) {
    if (vector.length != expectedDimensions) {
      throw ArgumentError(
        'Vector dimension mismatch: expected $expectedDimensions, got ${vector.length}'
      );
    }
    
    for (int i = 0; i < vector.length; i++) {
      final value = vector[i];
      if (value.isNaN) {
        throw ArgumentError('Vector contains NaN at index $i');
      }
      if (value.isInfinite) {
        throw ArgumentError('Vector contains infinite value at index $i');
      }
    }
  }
  
  static void validateTenantId(String tenantId) {
    if (tenantId.isEmpty) {
      throw ArgumentError('Tenant ID cannot be empty');
    }
    
    if (!RegExp(r'^[a-zA-Z0-9_-]+$').hasMatch(tenantId)) {
      throw ArgumentError('Tenant ID contains invalid characters: $tenantId');
    }
    
    if (tenantId.length > 64) {
      throw ArgumentError('Tenant ID too long: ${tenantId.length} characters (max 64)');
    }
  }
  
  static void validateObjectSize(dynamic object, int maxSizeBytes) {
    final serialized = jsonEncode(object);
    final sizeBytes = utf8.encode(serialized).length;
    
    if (sizeBytes > maxSizeBytes) {
      throw ArgumentError(
        'Object too large: $sizeBytes bytes (max $maxSizeBytes bytes)'
      );
    }
  }
}

Connection Management

class ConnectionManager {
  final VektagrafDatabase _database;
  final String _connectionString;
  final VektagrafConfig _config;
  Timer? _healthCheckTimer;
  
  ConnectionManager(this._database, this._connectionString, this._config);
  
  Future<void> ensureConnection() async {
    if (!_database.isOpen) {
      await _reconnect();
    }
  }
  
  Future<void> _reconnect() async {
    int attempts = 0;
    const maxAttempts = 3;
    
    while (attempts < maxAttempts) {
      try {
        await _database.open(_connectionString, config: _config);
        print('Database connection established');
        _startHealthChecks();
        return;
      } catch (e) {
        attempts++;
        print('Connection attempt $attempts failed: $e');
        
        if (attempts < maxAttempts) {
          await Future.delayed(Duration(seconds: 1 << attempts));
        }
      }
    }
    
    throw Exception('Failed to establish database connection after $maxAttempts attempts');
  }
  
  void _startHealthChecks() {
    _healthCheckTimer?.cancel();
    _healthCheckTimer = Timer.periodic(Duration(minutes: 1), (_) async {
      try {
        if (!_database.isOpen) {
          print('Database connection lost, attempting reconnection...');
          await _reconnect();
        }
      } catch (e) {
        print('Health check failed: $e');
      }
    });
  }
  
  void dispose() {
    _healthCheckTimer?.cancel();
  }
}

Resource Management

class ResourceManager {
  final Map<String, Timer> _cleanupTimers = {};
  final Map<String, int> _resourceCounts = {};
  
  void trackResource(String resourceType) {
    _resourceCounts[resourceType] = (_resourceCounts[resourceType] ?? 0) + 1;
    
    // Schedule cleanup if resource count is high
    if (_resourceCounts[resourceType]! > 1000) {
      _scheduleCleanup(resourceType);
    }
  }
  
  void releaseResource(String resourceType) {
    if (_resourceCounts.containsKey(resourceType)) {
      _resourceCounts[resourceType] = _resourceCounts[resourceType]! - 1;
      if (_resourceCounts[resourceType]! <= 0) {
        _resourceCounts.remove(resourceType);
      }
    }
  }
  
  void _scheduleCleanup(String resourceType) {
    _cleanupTimers[resourceType]?.cancel();
    _cleanupTimers[resourceType] = Timer(Duration(minutes: 5), () {
      _performCleanup(resourceType);
    });
  }
  
  void _performCleanup(String resourceType) {
    print('Performing cleanup for resource type: $resourceType');
    // Implement resource-specific cleanup
    _resourceCounts[resourceType] = 0;
    _cleanupTimers.remove(resourceType);
  }
  
  Map<String, int> getResourceCounts() => Map.from(_resourceCounts);
}

Monitoring and Alerting

Error Rate Monitoring

class ErrorRateMonitor {
  final Map<String, List<DateTime>> _errorOccurrences = {};
  final Duration _timeWindow;
  final int _alertThreshold;
  final void Function(String errorType, int count) _alertCallback;
  
  ErrorRateMonitor({
    this._timeWindow = const Duration(minutes: 5),
    this._alertThreshold = 10,
    required void Function(String errorType, int count) alertCallback,
  }) : _alertCallback = alertCallback;
  
  void recordError(String errorType) {
    final now = DateTime.now();
    _errorOccurrences.putIfAbsent(errorType, () => []).add(now);
    
    // Clean old occurrences
    _cleanOldOccurrences(errorType, now);
    
    // Check if alert threshold is exceeded
    final recentCount = _errorOccurrences[errorType]!.length;
    if (recentCount >= _alertThreshold) {
      _alertCallback(errorType, recentCount);
    }
  }
  
  void _cleanOldOccurrences(String errorType, DateTime now) {
    final cutoff = now.subtract(_timeWindow);
    _errorOccurrences[errorType]!.removeWhere((time) => time.isBefore(cutoff));
  }
  
  Map<String, int> getCurrentErrorRates() {
    final now = DateTime.now();
    final rates = <String, int>{};
    
    for (final entry in _errorOccurrences.entries) {
      _cleanOldOccurrences(entry.key, now);
      rates[entry.key] = entry.value.length;
    }
    
    return rates;
  }
}

Performance Monitoring

class PerformanceMonitor {
  final Map<String, List<Duration>> _operationTimes = {};
  final Duration _alertThreshold;
  final void Function(String operation, Duration time) _slowOperationCallback;
  
  PerformanceMonitor({
    this._alertThreshold = const Duration(seconds: 1),
    required void Function(String operation, Duration time) slowOperationCallback,
  }) : _slowOperationCallback = slowOperationCallback;
  
  Future<T> monitorOperation<T>(
    String operationName,
    Future<T> Function() operation,
  ) async {
    final stopwatch = Stopwatch()..start();
    
    try {
      final result = await operation();
      return result;
    } finally {
      stopwatch.stop();
      _recordOperationTime(operationName, stopwatch.elapsed);
    }
  }
  
  void _recordOperationTime(String operationName, Duration duration) {
    _operationTimes.putIfAbsent(operationName, () => []).add(duration);
    
    // Keep only recent measurements
    final recent = _operationTimes[operationName]!;
    if (recent.length > 100) {
      recent.removeAt(0);
    }
    
    // Alert on slow operations
    if (duration > _alertThreshold) {
      _slowOperationCallback(operationName, duration);
    }
  }
  
  Map<String, OperationStats> getOperationStats() {
    return _operationTimes.map((name, times) {
      if (times.isEmpty) {
        return MapEntry(name, OperationStats(
          operationName: name,
          count: 0,
          averageTime: Duration.zero,
          minTime: Duration.zero,
          maxTime: Duration.zero,
        ));
      }
      
      final totalMs = times.fold<int>(0, (sum, time) => sum + time.inMilliseconds);
      final avgTime = Duration(milliseconds: totalMs ~/ times.length);
      final minTime = times.reduce((a, b) => a < b ? a : b);
      final maxTime = times.reduce((a, b) => a > b ? a : b);
      
      return MapEntry(name, OperationStats(
        operationName: name,
        count: times.length,
        averageTime: avgTime,
        minTime: minTime,
        maxTime: maxTime,
      ));
    });
  }
}

class OperationStats {
  final String operationName;
  final int count;
  final Duration averageTime;
  final Duration minTime;
  final Duration maxTime;
  
  OperationStats({
    required this.operationName,
    required this.count,
    required this.averageTime,
    required this.minTime,
    required this.maxTime,
  });
  
  @override
  String toString() {
    return 'OperationStats(name: $operationName, count: $count, '
           'avg: ${averageTime.inMilliseconds}ms, '
           'min: ${minTime.inMilliseconds}ms, '
           'max: ${maxTime.inMilliseconds}ms)';
  }
}

Complete Error Reference

Error Code Quick Reference

Code Category Description Severity
VKG-DB-001 Database Connection failed Critical
VKG-DB-002 Database Already open Warning
VKG-DB-003 Database Not open Error
VKG-DB-004 Database Invalid object type Error
VKG-TX-001 Transaction Already active Warning
VKG-TX-002 Transaction Concurrency conflict Error
VKG-TX-003 Transaction Timeout Error
VKG-TX-004 Transaction Rollback failed Critical
VKG-SEC-001 Security Authentication failed Critical
VKG-SEC-002 Security Authorization failed Error
VKG-SEC-003 Security Rate limit exceeded Warning
VKG-SEC-004 Security Tenant limit exceeded Warning
VKG-VEC-001 Vector Dimension mismatch Error
VKG-VEC-002 Vector Invalid data Error
VKG-VEC-003 Vector Space not found Error
VKG-GRP-001 Graph Node not found Error
VKG-GRP-002 Graph Circular reference Error
VKG-SCH-001 Schema Parse error Critical
VKG-SCH-002 Schema Model not found Error
VKG-NET-001 Network Connection timeout Error
VKG-NET-002 Network Service unavailable Critical

Exception Hierarchy

VektagrafException
├── VektagrafDatabaseException
│   ├── VektagrafConnectionException
│   ├── VektagrafTransactionException
│   └── VektagrafConcurrencyException
├── VektagrafSecurityException
│   ├── VektagrafAuthenticationException
│   ├── VektagrafAuthorizationException
│   └── VektagrafRateLimitException
├── VektagrafValidationException
│   ├── VektagrafSchemaException
│   └── VektagrafInputException
├── VektagrafNetworkException
│   ├── VektagrafTimeoutException
│   └── VektagrafServiceUnavailableException
└── VektagrafResourceException
    ├── VektagrafMemoryException
    └── VektagrafStorageException

Summary

This chapter provided comprehensive error handling and troubleshooting guidance for Vektagraf:

  • Error Classification: Systematic categorization of all error types
  • Specific Error Codes: Detailed documentation of common errors and resolutions
  • Troubleshooting Procedures: Step-by-step diagnostic and resolution workflows
  • Performance Troubleshooting: Memory, query, and resource optimization
  • Automated Diagnostics: Tools for systematic problem identification
  • Error Prevention: Strategies for avoiding common issues
  • Monitoring and Alerting: Proactive error detection and performance monitoring

Use this reference to quickly identify, diagnose, and resolve issues in your Vektagraf applications. The systematic approach and comprehensive error coverage will help you maintain reliable, high-performance systems.

Next Steps

  • Chapter 26: Migration and Upgrade Guides - Version compatibility and upgrades
  • Appendix I: Complete API Reference - Detailed API documentation
  • Appendix II: Configuration Reference - Comprehensive configuration options
  • Part IV: Advanced Topics - Performance tuning and optimization
  • Part V: Enterprise Deployment - Production deployment patterns