--- title: "Error Handling" description: "Common errors and troubleshooting tips" canonical: "https://roomsharp.dev/docs/v0.4.7/error-handling" source: "src/content/v0.4.7/error-handling.mdx" --- # Error Handling ## Build/Compile-Time Errors ### Missing [PrimaryKey] **Error:** Entity 'User' does not have a [PrimaryKey] attribute **Solution:** Add [PrimaryKey] to exactly one property: ```csharp [Entity(TableName = "users")] public class User { [PrimaryKey(AutoGenerate = true)] public long Id { get; set; } // Required! public string Email { get; set; } } ``` ### Query Parameter Mismatch **Error:** Query parameter ':userId' does not match any method parameter **Solution:** Ensure parameter names match: ```csharp // ❌ Name mismatch [Query("SELECT * FROM users WHERE Id = :userId")] Task GetByIdAsync(long id); // ✅ Names match [Query("SELECT * FROM users WHERE Id = :userId")] Task GetByIdAsync(long userId); ``` ### Invalid Return Type **Error:** [Insert] method must return void, int, or long **Solution:** Use appropriate return type: ```csharp // ✅ Valid return types for [Insert] [Insert] void Insert(User user); [Insert] long Insert(User user); // Returns row ID [Insert] Task InsertAsync(User user); [Insert] Task InsertAsync(User user); ``` ### Source Generator Not Running **Error:** Type 'AppDatabaseImpl' not found **Solutions:** 1. Clean and rebuild solution 2. Check RoomSharp package is installed 3. Verify entities have [Entity] attribute 4. Check build output for generator warnings 5. Enable generator logging: ```xml true Generated ``` ## Runtime Errors ### Connection Errors **Error:** Unable to open database file **Solutions:** - Check file path is correct - Ensure directory exists - Verify write permissions - Check file is not locked by another process ```csharp try { var db = RoomDatabase.Builder() .UseSqlite("app.db") .Build(); } catch (Exception ex) { _logger.LogError(ex, "Failed to open database"); // Handle error appropriately } ``` ### Unique Constraint Violation **Error:** UNIQUE constraint failed: users.email **Solution:** Check for duplicates or use upsert: ```csharp // Use [Upsert] to handle duplicates [Upsert] long UpsertUser(User user); // Or check first var existing = await dao.FindByEmailAsync(email); if (existing == null) { await dao.InsertAsync(user); } ``` ### Foreign Key Constraint **Error:** FOREIGN KEY constraint failed **Solutions:** - Ensure referenced entity exists first - Use transactions to maintain referential integrity - Configure cascade actions appropriately ```csharp [Entity(TableName = "todos")] public class Todo { [PrimaryKey(AutoGenerate = true)] public long Id { get; set; } [ForeignKey(Entity = typeof(TodoList), OnDelete = ForeignKeyAction.Cascade)] public long ListId { get; set; } } ``` ### Null Reference Errors **Error:** Nullable object must have a value **Solution:** Use nullable types for optional columns: ```csharp // ✅ Proper nullable handling [Entity(TableName = "users")] public class User { [PrimaryKey] public long Id { get; set; } public required string Email { get; set; } // NOT NULL public string? Name { get; set; } // NULL allowed public DateTime? UpdatedAt { get; set; } // NULL allowed } ``` ## Transaction Errors ### Nested Transaction Issues **Solution:** RoomSharp handles nested transactions automatically. Ensure you're not manually managing transactions within [Transaction] methods. ### Transaction Deadlocks **Solutions:** - Keep transactions short - Always acquire locks in same order - Use WAL mode for SQLite - Implement retry logic ```csharp var db = RoomDatabase.Builder() .UseSqlite("app.db") .SetJournalMode(JournalMode.WAL) // Enables concurrent reads .Build(); ``` ## Type Converter Errors ### Conversion Failures **Error:** Failed to convert value to type **Solution:** Handle edge cases in converters: ```csharp public class SafeJsonConverter : TypeConverter { public override string Convert(T value) { return value == null ? "" : JsonSerializer.Serialize(value); } public override T ConvertBack(string value) { if (string.IsNullOrEmpty(value)) return default!; try { return JsonSerializer.Deserialize(value)!; } catch (JsonException ex) { _logger.LogWarning(ex, "Failed to deserialize JSON"); return default!; } } } ``` ## Debugging Tips ### 1. Enable Logging ```csharp var db = RoomDatabase.Builder() .UseSqlite("app.db") .AddCallback(new LoggingCallback(logger)) .Build(); public class LoggingCallback : RoomDatabaseCallback { private readonly ILogger _logger; public LoggingCallback(ILogger logger) => _logger = logger; public override void OnCreate(DbConnection connection) { _logger.LogInformation("Database created"); } public override void OnOpen(DbConnection connection) { _logger.LogInformation("Database opened"); } } ``` ### 2. View Generated Code Navigate to: - Solution Explorer → Dependencies → Analyzers → RoomSharp.SourceGenerator - Or check `obj/Debug/net8.0/generated/` ### 3. SQL Profiling ```csharp public class SqlLogger : IQueryExecutor { public T ExecuteQuery(IDbCommand cmd, Func handler) { Console.WriteLine($"SQL: {cmd.CommandText}"); foreach (IDbDataParameter p in cmd.Parameters) { Console.WriteLine($" {p.ParameterName} = {p.Value}"); } return handler(cmd); } } var db = RoomDatabase.Builder() .UseSqlite("app.db") .SetQueryExecutor(new SqlLogger()) .Build(); ``` ## Common Issues & Solutions | Issue | Solution | |-------|----------| | Database locked | Enable WAL mode, reduce transaction duration | | Slow queries | Add indexes, optimize SQL, use EXPLAIN QUERY PLAN | | Memory leaks | Dispose connections, use auto-close timeout | | Migration failures | Test migrations, use FallbackToDestructiveMigration for dev | ## Getting Help - Check the [FAQ](/docs/v0.4.7/faq) for common questions - Review [generated code](/docs/v0.4.7/generated-code) to understand what's happening - Enable detailed logging to diagnose issues - File an issue on GitHub with minimal reproduction ## Next Steps - [FAQ](/docs/v0.4.7/faq) - Frequently asked questions - [Generated Code](/docs/v0.4.7/generated-code) - Understand the generated implementation - [Performance Notes](/docs/v0.4.7/performance) - Optimize your use of RoomSharp