⚠️ Preview Release: RoomSharp is currently in Preview. Learn more →

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:

C#
[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:

C#
// ❌ 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:

C#
// ✅ 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:

  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
    <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
C#
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:

C#
// 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
C#
[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:

C#
// ✅ 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
C#
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:

C#
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

C#
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

C#
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