Error Handling
Common errors and troubleshooting tips
Build/Compile-Time Errors
Missing [PrimaryKey]
Error: Entity 'User' does not have a [PrimaryKey] attribute
Solution: Add [PrimaryKey] to exactly one property:
[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:
// ❌ Name mismatch
[Query("SELECT * FROM users WHERE Id = :userId")]
Task<User?> GetByIdAsync(long id);
// ✅ Names match
[Query("SELECT * FROM users WHERE Id = :userId")]
Task<User?> GetByIdAsync(long userId);
Invalid Return Type
Error: [Insert] method must return void, int, or long
Solution: Use appropriate return type:
// ✅ 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<long> InsertAsync(User user);
Source Generator Not Running
Error: Type 'AppDatabaseImpl' not found
Solutions:
- Clean and rebuild solution
- Check RoomSharp package is installed
- Verify entities have [Entity] attribute
- Check build output for generator warnings
- Enable generator logging:
XML
<PropertyGroup> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> <CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath> </PropertyGroup>
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
try
{
var db = RoomDatabase.Builder<AppDatabaseImpl>()
.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:
// 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
[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:
// ✅ 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
var db = RoomDatabase.Builder<AppDatabaseImpl>()
.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:
public class SafeJsonConverter<T> : TypeConverter<T, string>
{
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<T>(value)!;
}
catch (JsonException ex)
{
_logger.LogWarning(ex, "Failed to deserialize JSON");
return default!;
}
}
}
Debugging Tips
1. Enable Logging
var db = RoomDatabase.Builder<AppDatabaseImpl>()
.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 op ened");
}
}
2. View Generated Code
Navigate to:
- Solution Explorer → Dependencies → Analyzers → RoomSharp.SourceGenerator
- Or check
obj/Debug/net8.0/generated/
3. SQL Profiling
public class SqlLogger : IQueryExecutor
{
public T ExecuteQuery<T>(IDbCommand cmd, Func<IDbCommand, T> 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<AppDatabaseImpl>()
.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 for common questions
- Review generated code to understand what's happening
- Enable detailed logging to diagnose issues
- File an issue on GitHub with minimal reproduction
Next Steps
- FAQ - Frequently asked questions
- Generated Code - Understand the generated implementation
- Performance Notes - Optimize your use of RoomSharp

