affaan-m/ECC · error
error
Error message
error
What it means
After the DB message is queued, send awaits a oneshot ack from the writer. Ok(Err(error)) means the writer received the message but the underlying DB operation failed; the inner error string is re-wrapped verbatim as anyhow "error"-style message. This is a propagated persistence failure, not a channel failure.
Solutions
- Inspect the inner error text (it is embedded in this error) to find the actual DB failure
- Retry the write after the lock holder releases the database
- Back up/repair or recreate the session DB if the schema is corrupted
Example fix
// before
Err(anyhow::anyhow!(error))
// after
Err(anyhow::anyhow!("DB write failed: {error}")) // preserve cause in message Defensive patterns
Strategy: retry
Validate before calling
// check DB writability before writes let f = std::fs::OpenOptions::new().append(true).open(&db_path)?;
Try / catch
match db_writer.update_state(state).await {
Err(e) if is_db_error(&e) => {
tokio::time::sleep(Duration::from_millis(250)).await;
db_writer.update_state(state).await?; // retry once after transient lock
}
r => r?,
} Prevention
- Avoid opening the session SQLite with other tools while the session runs
- Watch disk space/quotas on the state directory
- Keep schema versions in sync between CLI and runtime
When it happens
Trigger: run_db_writer executes the write against SQLite and returns Err — disk full, schema mismatch, locked database, constraint violation — and the ack carries that error back to update_state/update_pid/append_output_line/touch_heartbeat.
Common situations: SQLite file locked by another process (concurrent CLI inspecting the session); disk quota exceeded; DB schema version drift after an upgrade.
Related errors
- an active harness configuration already exists
- atomic promotion compare-and-swap failed
- atomic rollback compare-and-swap failed
- baseline is not the active harness configuration
- candidate alias integrity verification failed
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/c5eb3beaa59d0163.
Report an issue: GitHub.
Appendix: source
Thrown at ecc2/src/session/runtime.rs:75
.await
}
async fn touch_heartbeat(&self) -> Result<()> {
self.send(|ack| DbMessage::TouchHeartbeat { ack }).await
}
async fn send<F>(&self, build: F) -> Result<()>
where
F: FnOnce(oneshot::Sender<DbAck>) -> DbMessage,
{
let (ack_tx, ack_rx) = oneshot::channel();
self.tx
.send(build(ack_tx))
.map_err(|_| anyhow::anyhow!("DB writer channel closed"))?;
match ack_rx.await {
Ok(Ok(())) => Ok(()),
Ok(Err(error)) => Err(anyhow::anyhow!(error)),
Err(_) => Err(anyhow::anyhow!("DB writer acknowledgement dropped")),
}
}
}
fn run_db_writer(db_path: PathBuf, session_id: String, mut rx: mpsc::UnboundedReceiver<DbMessage>) {
let (opened, open_error) = match StateStore::open(&db_path) {
Ok(db) => (Some(db), None),
Err(error) => (None, Some(error.to_string())),
};
while let Some(message) = rx.blocking_recv() {
match message {
DbMessage::UpdateState { state, ack } => {
let result = match opened.as_ref() {
Some(db) => db
.update_state(&session_id, &state)
.map_err(|error| error.to_string()),View on GitHub (pinned to 8321021c54)