windmill-labs/windmill · error

Database write failed: {e:?}

Error message

Database write failed: {e:?}

What it means

OSS agent memory writer: `write_to_memory` wraps failures of `memory_common::write_to_db`, which persists the agent's messages for a conversation step. Only invoked when `messages` is non-empty; a failure means the conversation history for this step was not saved and later steps will resume without it.

Source

Thrown at backend/windmill-worker/src/memory_oss.rs:40

}

/// Write AI agent memory to storage
/// In OSS: always writes to database
#[cfg(not(all(feature = "private", feature = "enterprise")))]
pub async fn write_to_memory(
    db: &DB,
    workspace_id: &str,
    conversation_id: Uuid,
    step_id: &str,
    messages: &[OpenAIMessage],
) -> anyhow::Result<()> {
    if messages.is_empty() {
        return Ok(());
    }

    memory_common::write_to_db(db, workspace_id, conversation_id, step_id, messages)
        .await
        .map_err(|e| anyhow::anyhow!("Database write failed: {e:?}"))
}

/// Delete all memory for a conversation from storage
/// In OSS: always deletes from database
#[cfg(not(all(feature = "private", feature = "enterprise")))]
pub async fn delete_conversation_memory(
    db: &DB,
    workspace_id: &str,
    conversation_id: Uuid,
) -> anyhow::Result<()> {
    memory_common::delete_conversation_from_db(db, workspace_id, conversation_id)
        .await
        .map_err(|e| anyhow::anyhow!("Database delete failed: {e:?}"))
}

View on GitHub (pinned to e474e8803c)

Solutions

  1. Inspect the `{e:?}` chain for the root cause (connection, permission, or size).
  2. Check Postgres health: connectivity, disk space, connection pool saturation.
  3. Ensure migrations have run so memory tables exist.
  4. Re-run the agent step — the write happens after execution, so re-running regenerates and re-saves the messages.
Defensive patterns

Strategy: retry

Validate before calling

// check writable DB + table presence before long agent runs
psql "$DATABASE_URL" -c "insert into agent_memory default values; rollback;" >/dev/null || echo 'DB not writable'

Try / catch

// retry the post-step write once; it happens after execution so it's safe to redo
if let Err(e) = write_to_memory(&db, w_id, conv_id, &step_id, &msgs).await {
    log::warn!("memory write failed: {e:?}; retrying once");
    write_to_memory(&db, w_id, conv_id, &step_id, &msgs).await?;
}

Prevention

When it happens

Trigger: `run_agent` finishing a step calls `write_to_memory(db, workspace_id, conversation_id, step_id, messages)`; the DB insert fails — connection loss, write permission denied, table missing after an upgrade, row size limits exceeded by very large message payloads.

Common situations: Postgres connection pool exhausted under heavy agent concurrency; database in read-only mode (disk full); messages JSON exceeding column/row limits; OSS instance not migrated to the version that introduced memory tables.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/5d5bdf95e84a36f5. Report an issue: GitHub.