{"record":{"id":"a791057a16da2a26","repo":"Zackriya-Solutions/meetily","slug":"db-error-a79105","errorCode":null,"errorMessage":"DB error: {}","messagePattern":"DB error: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"frontend/src-tauri/src/audio/retranscription.rs","lineNumber":431,"sourceCode":"\n    // Check for cancellation\n    if RETRANSCRIPTION_CANCELLED.load(Ordering::SeqCst) {\n        return Err(anyhow!(\"Retranscription cancelled\"));\n    }\n\n    emit_progress(&app, &meeting_id, \"saving\", 80, \"Saving transcripts...\");\n\n    // Create transcript segments with proper timestamps from VAD\n    let segments = create_transcript_segments(&all_transcripts);\n\n    // Save to database\n    let app_state = app\n        .try_state::<AppState>()\n        .ok_or_else(|| anyhow!(\"App state not available\"))?;\n\n    // Wrap delete+insert+update in a transaction to prevent data loss\n    let pool = app_state.db_manager.pool();\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    sqlx::query(\"DELETE FROM transcripts WHERE meeting_id = ?\")\n        .bind(&meeting_id)\n        .execute(&mut *tx)\n        .await\n        .map_err(|e| anyhow!(\"Failed to delete existing transcripts: {}\", e))?;\n\n    for segment in &segments {\n        sqlx::query(\n            \"INSERT INTO transcripts (id, meeting_id, transcript, timestamp, audio_start_time, audio_end_time, duration)\n             VALUES (?, ?, ?, ?, ?, ?, ?)\"\n        )\n        .bind(&segment.id)\n        .bind(&meeting_id)\n        .bind(&segment.text)","sourceCodeStart":413,"sourceCodeEnd":449,"githubUrl":"https://github.com/Zackriya-Solutions/meetily/blob/0281737d87d26352fb0adc78c8c0975f691b23d1/frontend/src-tauri/src/audio/retranscription.rs#L413-L449","documentation":"sqlx failed to acquire a connection from the SQLite pool. The inner '{}' says why: typically 'database is locked' (SQLITE_BUSY, another connection or process is writing), the pool was closed, or a disk I/O error. Note the pool is created without busy_timeout/WAL options, so lock contention surfaces immediately instead of waiting.","triggerScenarios":"A second app instance or another in-app writer (import, live transcript save) holds the SQLite write lock at save time; Pool::close was called; the DB file was deleted or the disk filled while the app runs.","commonSituations":"Two instances of the app open the same data directory; retranscription save colliding with a background DB write; an external sqlite3 CLI inspecting the file.","solutions":["Read the inner sqlx error string to classify: locked vs pool closed vs I/O error.","Close every other process using the database file, then retry the retranscription.","Configure the SQLite pool with WAL journal mode and a busy_timeout so writers wait instead of failing.","If 'pool closed' appears, the app is shutting down - restart and retry."],"exampleFix":"// before (typical pool creation without wait options)\nlet pool = SqlitePoolOptions::new().connect(&db_url).await?;\n\n// after: wait for locks instead of failing instantly\nlet opts = SqliteConnectOptions::from_url(&db_url)?\n    .journal_mode(SqliteJournalMode::Wal)\n    .busy_timeout(std::time::Duration::from_secs(5));\nlet pool = SqlitePoolOptions::new().connect_with(opts).await?;","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Retry acquisition with backoff for transient locks\nlet conn = match pool.acquire().await {\n    Ok(c) => c,\n    Err(e) => {\n        tokio::time::sleep(std::time::Duration::from_millis(500)).await;\n        pool.acquire().await.map_err(|e2| anyhow!(\"DB error: {e2} (first: {e})\"))?\n    }\n};","preventionTips":["Run only one app instance per data directory.","Configure the SQLite pool with WAL + busy_timeout so lock contention waits instead of erroring.","Keep an eye on disk space and file permissions for the DB."],"tags":["sqlx","sqlite","connection-pool","database-locked"],"backgroundTag":"database-connection-acquire-failed","analyzedSha":"0281737d87d26352fb0adc78c8c0975f691b23d1","analyzedAt":"2026-08-16T20:57:52.567Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}