Zackriya-Solutions/meetily · error

Failed to insert transcript: {}

Error message

Failed to insert transcript: {}

What it means

One of the per-segment INSERT INTO transcripts statements failed; the loop runs once per transcript, so a single bad segment aborts the import after all transcription work completed. The {} names the SQLite cause: schema drift on the transcripts table, a constraint violation (NOT NULL on timestamp/duration/text), or a disk I/O error.

Source

Thrown at frontend/src-tauri/src/audio/import.rs:734

    .await
    .map_err(|e| anyhow!("Failed to create meeting: {}", e))?;

    // Insert transcripts
    for segment in segments {
        sqlx::query(
            "INSERT INTO transcripts (id, meeting_id, transcript, timestamp, audio_start_time, audio_end_time, duration)
             VALUES (?, ?, ?, ?, ?, ?, ?)",
        )
        .bind(&segment.id)
        .bind(&meeting_id)
        .bind(&segment.text)
        .bind(&segment.timestamp)
        .bind(segment.audio_start_time)
        .bind(segment.audio_end_time)
        .bind(segment.duration)
        .execute(&mut *tx)
        .await
        .map_err(|e| anyhow!("Failed to insert transcript: {}", e))?;
    }

    tx.commit()
        .await
        .map_err(|e| anyhow!("Failed to commit transaction: {}", e))?;

    info!(
        "Created meeting '{}' with {} transcripts",
        meeting_id,
        segments.len()
    );

    Ok(meeting_id)
}

/// Get or initialize the Whisper engine
async fn get_or_init_whisper<R: Runtime>(
    app: &AppHandle<R>,

View on GitHub (pinned to 0281737d87)

Solutions

  1. Read the {} — 'no such column' indicates schema drift, 'constraint failed' names the column with bad data
  2. Validate segments before the DB call: non-empty text and finite numeric fields on every segment
  3. Re-run migrations and verify PRAGMA table_info(transcripts) matches the INSERT column list
  4. Log the failing segment id and fields when mapping the error so the bad row is identifiable

Example fix

// before — any bad segment aborts the import late
.execute(&mut *tx).await
    .map_err(|e| anyhow!("Failed to insert transcript: {}", e))?;

// after — validate segment data before inserting
for segment in segments {
    if segment.text.trim().is_empty() {
        warn!("skipping empty segment {}", segment.id);
        continue;
    }
    if !segment.duration.is_finite() || !segment.audio_start_time.is_finite() {
        warn!("segment {} has non-finite times, skipping", segment.id);
        continue;
    }
    // ...bind and execute
}
Defensive patterns

Strategy: validation

Validate before calling

// validate every segment before the DB write
fn segments_writable(segments: &[TranscriptSegment]) -> bool {
    segments.iter().all(|s| {
        !s.text.trim().is_empty()
            && s.duration.is_finite()
            && s.audio_start_time.is_finite()
            && s.audio_end_time.is_finite()
    })
}

Try / catch

Wrap the per-segment insert: on error, log the failing segment.id and its field values, then decide — skip that row and continue inside the transaction for data errors; abort only for schema/I-O errors.

Prevention

When it happens

Trigger: The transcripts table missing or missing columns after schema drift; a segment carrying NULL or NaN in timestamp/audio_start_time/audio_end_time/duration from create_transcript_segments edge cases; disk filling up partway through the insert loop.

Common situations: Mixed app versions sharing one database; degenerate segments after silence-splitting producing non-finite durations; very long imports exhausting disk mid-loop.

Related errors


AI-assisted analysis of Zackriya-Solutions/meetily@0281737d87 (2026-08-16). Data as JSON: /api/errors/420b8dbcc4770ff9. Report an issue: GitHub.