diff --git a/src/core/error.rs b/src/core/error.rs index b9c5f2f..7d809fc 100644 --- a/src/core/error.rs +++ b/src/core/error.rs @@ -180,7 +180,13 @@ impl LoreError { Self::DatabaseLocked { .. } => ErrorCode::DatabaseLocked, Self::MigrationFailed { .. } => ErrorCode::MigrationFailed, Self::TokenNotSet { .. } => ErrorCode::TokenNotSet, - Self::Database(_) => ErrorCode::DatabaseError, + Self::Database(e) => { + if e.sqlite_error_code() == Some(rusqlite::ErrorCode::DatabaseBusy) { + ErrorCode::DatabaseLocked + } else { + ErrorCode::DatabaseError + } + } Self::Http(_) => ErrorCode::GitLabNetworkError, Self::Json(_) => ErrorCode::InternalError, Self::Io(_) => ErrorCode::IoError, @@ -218,14 +224,20 @@ impl LoreError { "Wait for other sync to complete or use --force.\n\n Example:\n lore ingest --force\n lore ingest issues --force", ), Self::MigrationFailed { .. } => Some( - "Check database file permissions or reset with 'lore reset'.\n\n Example:\n lore migrate\n lore reset --yes", + "Check database file permissions and try again.\n\n Example:\n lore migrate\n lore doctor", ), Self::TokenNotSet { .. } => Some( "Set your token:\n\n lore token set\n\n Or export to your shell:\n\n export GITLAB_TOKEN=glpat-xxxxxxxxxxxx\n\n Your token needs the read_api scope.", ), - Self::Database(_) => Some( - "Check database file permissions or reset with 'lore reset'.\n\n Example:\n lore doctor\n lore reset --yes", - ), + Self::Database(e) => { + if e.sqlite_error_code() == Some(rusqlite::ErrorCode::DatabaseBusy) { + Some( + "Another process has the database locked. Wait a moment and retry.\n\n Common causes:\n - A cron sync is running (lore cron status)\n - Another lore command is active", + ) + } else { + Some("Check database file permissions.\n\n Example:\n lore doctor") + } + } Self::Http(_) => Some("Check network connection"), Self::NotFound(_) => { Some("Verify the entity exists.\n\n Example:\n lore issues\n lore mrs") @@ -267,6 +279,11 @@ impl LoreError { Self::OllamaUnavailable { .. } => vec!["ollama serve"], Self::OllamaModelNotFound { .. } => vec!["ollama pull nomic-embed-text"], Self::DatabaseLocked { .. } => vec!["lore ingest --force"], + Self::Database(e) + if e.sqlite_error_code() == Some(rusqlite::ErrorCode::DatabaseBusy) => + { + vec!["lore cron status"] + } Self::EmbeddingsNotBuilt => vec!["lore embed"], Self::EmbeddingFailed { .. } => vec!["lore embed --retry-failed"], Self::MigrationFailed { .. } => vec!["lore migrate"],