{"record":{"id":"ad5b05df5d7774a7","repo":"windmill-labs/windmill","slug":"database-read-failed-e","errorCode":null,"errorMessage":"Database read failed: {e:?}","messagePattern":"Database read failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/windmill-worker/src/memory_oss.rs","lineNumber":21,"sourceCode":"pub use crate::memory_ee::*;\n\n#[cfg(not(all(feature = \"private\", feature = \"enterprise\")))]\nuse {\n    crate::memory_common, uuid::Uuid, windmill_ai::types::OpenAIMessage, windmill_common::db::DB,\n};\n\n/// Read AI agent memory from storage\n/// In OSS: always reads from database\n#[cfg(not(all(feature = \"private\", feature = \"enterprise\")))]\npub async fn read_from_memory(\n    db: &DB,\n    workspace_id: &str,\n    conversation_id: Uuid,\n    step_id: &str,\n) -> anyhow::Result<Option<Vec<OpenAIMessage>>> {\n    memory_common::read_from_db(db, workspace_id, conversation_id, step_id)\n        .await\n        .map_err(|e| anyhow::anyhow!(\"Database read failed: {e:?}\"))\n}\n\n/// Write AI agent memory to storage\n/// In OSS: always writes to database\n#[cfg(not(all(feature = \"private\", feature = \"enterprise\")))]\npub async fn write_to_memory(\n    db: &DB,\n    workspace_id: &str,\n    conversation_id: Uuid,\n    step_id: &str,\n    messages: &[OpenAIMessage],\n) -> anyhow::Result<()> {\n    if messages.is_empty() {\n        return Ok(());\n    }\n\n    memory_common::write_to_db(db, workspace_id, conversation_id, step_id, messages)\n        .await","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/windmill-worker/src/memory_oss.rs#L3-L39","documentation":"OSS agent memory reader: `read_from_memory` wraps any failure of `memory_common::read_from_db` (which loads prior OpenAI-format messages for an agent conversation step from the database). The `{e:?}` debug format exposes the full error chain. The agent run fails because conversation history could not be loaded.","triggerScenarios":"`run_agent` starting a new step calls `read_from_memory(db, workspace_id, conversation_id, step_id)`; the underlying DB query fails — connection drop, table missing (pre-migration database), or the row/tuple shape can't be deserialized into `Vec<OpenAIMessage>`.","commonSituations":"Self-hosted OSS instance upgraded without running migrations (memory tables absent); Postgres briefly unavailable; corrupted JSON stored in the memory column from an older schema version.","solutions":["Read the `{e:?}` chain in the job error to identify the root cause (connection vs. relation-missing vs. deserialization).","Run pending Windmill database migrations so the memory tables exist.","Verify DATABASE_URL connectivity from the worker.","If deserialization fails, delete the corrupted conversation memory rows and re-run the agent step."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// verify memory tables exist before running agents\npsql \"$DATABASE_URL\" -c '\\d agent_memory' || echo 'run migrations first'","typeGuard":null,"tryCatchPattern":"match read_from_memory(&db, w_id, conv_id, &step_id).await {\n    Ok(msgs) => msgs,\n    Err(e) => { log::warn!(\"memory read failed, starting fresh: {e:?}\"); None }\n}","preventionTips":["Run database migrations on every upgrade before dispatching jobs","Alert on Postgres connectivity from worker nodes","Delete conversations with corrupted memory rows rather than retrying blindly"],"tags":["database","agent","memory","read"],"backgroundTag":"database-read-failed","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}