{"record":{"id":"1c8572082f307dce","repo":"Zackriya-Solutions/meetily","slug":"failed-to-start-transaction","errorCode":null,"errorMessage":"Failed to start transaction: {}","messagePattern":"Failed to start transaction: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/src-tauri/src/audio/import.rs","lineNumber":703,"sourceCode":"    );\n}\n\n\n/// Create a new meeting with transcripts in the database\nasync fn create_meeting_with_transcripts(\n    pool: &sqlx::SqlitePool,\n    title: &str,\n    segments: &[TranscriptSegment],\n    folder_path: String,\n) -> Result<String> {\n    let meeting_id = format!(\"meeting-{}\", Uuid::new_v4());\n    let now = chrono::Utc::now();\n\n    // Start transaction\n    let mut conn = pool.acquire().await.map_err(|e| anyhow!(\"DB error: {}\", e))?;\n    let mut tx = sqlx::Connection::begin(&mut *conn)\n        .await\n        .map_err(|e| anyhow!(\"Failed to start transaction: {}\", e))?;\n\n    // Insert meeting\n    sqlx::query(\n        \"INSERT INTO meetings (id, title, created_at, updated_at, folder_path)\n         VALUES (?, ?, ?, ?, ?)\",\n    )\n    .bind(&meeting_id)\n    .bind(title)\n    .bind(now)\n    .bind(now)\n    .bind(&folder_path)\n    .execute(&mut *tx)\n    .await\n    .map_err(|e| anyhow!(\"Failed to create meeting: {}\", e))?;\n\n    // Insert transcripts\n    for segment in segments {\n        sqlx::query(","sourceCodeStart":685,"sourceCodeEnd":721,"githubUrl":"https://github.com/Zackriya-Solutions/meetily/blob/0281737d87d26352fb0adc78c8c0975f691b23d1/frontend/src-tauri/src/audio/import.rs#L685-L721","documentation":"`sqlx::Connection::begin` failed to start the write transaction — SQLite refused BEGIN or could not take the write lock. The classic cause is SQLITE_BUSY/SQLITE_LOCKED: another connection (live recording writer, summary job, second app instance) holds the database write lock longer than busy_timeout allows. Note acquire() on the line above already succeeded, so the connection itself is healthy.","triggerScenarios":"Calling create_meeting_with_transcripts while another pooled connection is mid-write; the database in rollback-journal mode with concurrent readers blocking the writer; DB file on a locked or cloud-synced location.","commonSituations":"Importing while a live meeting recording is being saved; two app instances pointing at the same DB; the DB directory under OneDrive/Dropbox sync holding advisory locks.","solutions":["Enable WAL and busy_timeout on connect (PRAGMA journal_mode=WAL; PRAGMA busy_timeout=5000;) so BEGIN waits instead of failing","Retry BEGIN on SQLITE_BUSY with short backoff","Avoid running imports concurrently with other heavy DB write paths — the ImportGuard blocks concurrent imports, not other writers","Move the DB off cloud-synced or network folders"],"exampleFix":"// before\nlet mut tx = sqlx::Connection::begin(&mut *conn).await\n    .map_err(|e| anyhow!(\"Failed to start transaction: {}\", e))?;\n\n// after — configure WAL + busy_timeout once, at pool creation\nSqlitePoolOptions::new()\n    .max_connections(5)\n    .after_connect(|conn, _| Box::pin(async move {\n        sqlx::query(\"PRAGMA journal_mode=WAL; PRAGMA busy_timeout=5000;\")\n            .execute(&mut *conn)\n            .await?;\n        Ok(())\n    }))","handlingStrategy":"retry","validationCode":"-- verify journal mode once, at startup\nPRAGMA journal_mode; -- should report 'wal'","typeGuard":null,"tryCatchPattern":"Retry Connection::begin twice with 250-500ms backoff when the sqlx error string contains 'database is locked'; give up after that and report contention rather than retrying forever.","preventionTips":["Enable WAL journal and busy_timeout on every connection at pool creation","Do not import while a live meeting is being recorded/saved","Keep the DB off cloud-synced and network folders"],"tags":["sqlx","sqlite","transaction","sqlite-busy","wal","rust"],"backgroundTag":"sqlite-database-locked","analyzedSha":"0281737d87d26352fb0adc78c8c0975f691b23d1","analyzedAt":"2026-08-16T20:57:52.567Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}