nikivdev/code · error

insert failed: {:?}

Error message

insert failed: {:?}

What it means

insert_task_run persists a task-run record into the groove database by building a raw SQL string and executing it. When db.execute fails, the underlying error is wrapped as "insert failed: {:?}". The most common root cause is sql_escape, which replaces single quotes with backticks instead of proper escaping, so values containing backticks, percent signs, or overly long content can still break the SQL.

Source

Thrown at src/jazz_state.rs:202

        VALUES ('{}', {}, '{}', '{}', '{}', '{}', {}, {}, {}, {}, '{}', {}, '{}')",
        sql_escape(&record.project_root),
        project_name,
        sql_escape(&record.config_path),
        sql_escape(&record.task_name),
        sql_escape(&record.command),
        sql_escape(&record.user_input),
        if record.success { "true" } else { "false" },
        status,
        duration_ms,
        timestamp_ms,
        sql_escape(&record.flow_version),
        if record.used_flox { "true" } else { "false" },
        sql_escape(&output),
    );

    db.execute(&sql)
        .map(|_| ())
        .map_err(|err| anyhow::anyhow!("insert failed: {:?}", err))
}

fn sql_escape(value: &str) -> String {
    // Replace single quotes with backticks since groove SQL doesn't handle '' escaping well
    // Also remove null bytes
    value.replace('\'', "`").replace('\0', "")
}

fn truncate_output(value: &str, limit: usize) -> String {
    if value.len() <= limit {
        return value.to_string();
    }

    let mut start = value.len() - limit;
    while start < value.len() && !value.is_char_boundary(start) {
        start += 1;
    }

View on GitHub (pinned to a747e741ae)

Solutions

  1. Inspect the wrapped inner error with RUST_BACKTRACE=1 to see the actual DB error
  2. Check the task output/content being inserted for backticks or odd characters that sql_escape mishandles
  3. Verify the task_runs table exists and matches the columns in the INSERT
  4. Confirm the database file/connection is writable and not locked

Example fix

// before
value.replace('\'', "`").replace('\0', "")
// after
// double the quotes instead of substituting backticks, if the backend supports ''
value.replace('\'', "''").replace('\0', "")
Defensive patterns

Strategy: try-catch

Validate before calling

// before insert
fn validate_output(output: &str) -> Result<(), String> {
    if output.contains('`') || output.len() > 1_000_000 {
        Err("output contains characters/size that may break the insert".into())
    } else { Ok(()) }
}

Try / catch

match record_task_run(&record) {
    Err(e) if e.to_string().contains("insert failed") => {
        eprintln!("DB insert failed, retrying with sanitized output: {e:#}");
        // retry with sanitized/truncated output
    }
    Err(e) => return Err(e),
    Ok(()) => {}
}

Prevention

When it happens

Trigger: record_task_run calls insert_task_run and db.execute(&sql) returns Err — e.g. the SQL text is malformed after escaping, the output/fields contain characters that break the statement, the table doesn't exist, or the database file/connection is unavailable.

Common situations: Task output contains backticks or control characters that survive sql_escape and corrupt the statement; schema drift after a version change so the task_runs table/columns are missing; database locked or on read-only media.

Related errors


AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01). Data as JSON: /api/errors/6192d6e01a4e12cf. Report an issue: GitHub.