zeroclaw-labs/zeroclaw · error
cannot rename agent memory to `{to}`: an existing memory sto
Error message
cannot rename agent memory to `{to}`: an existing memory store under that alias has {to_rows} row(s); refusing to merge What it means
PostgresMemory::rename_agent refuses to overwrite an existing agent's memory: inside a transaction it counts the destination alias's memory rows, and any row count > 0 aborts, because renaming would silently merge two memory stores irreversibly (the transaction would otherwise delete the empty destination agent row and re-point the source alias). The message reports the conflicting alias and row count.
Source
Thrown at crates/zeroclaw-memory/src/postgres.rs:640
let client = self.client.get().clone();
let qualified_agents = self.qualified_agents.clone();
let qualified_table = self.qualified_table.clone();
let from = from.to_string();
let to = to.to_string();
run_on_os_thread(move || -> Result<usize> {
let mut client = client.lock();
let mut tx = client.transaction()?;
let to_rows: i64 = tx
.query_one(
&format!(
"SELECT COUNT(*) FROM {qualified_table} WHERE agent_id = (SELECT id FROM {qualified_agents} WHERE alias = $1)"
),
&[&to],
)?
.get(0);
if to_rows > 0 {
anyhow::bail!(
"cannot rename agent memory to `{to}`: an existing memory store under that alias has {to_rows} row(s); refusing to merge"
);
}
tx.execute(
&format!("DELETE FROM {qualified_agents} WHERE alias = $1"),
&[&to],
)?;
let updated = tx.execute(
&format!("UPDATE {qualified_agents} SET alias = $2 WHERE alias = $1"),
&[&from, &to],
)?;
tx.commit()?;
usize::try_from(updated).context("PostgreSQL returned an oversized update count")
})
.await
}
async fn count_agent(&self, agent_alias: &str) -> Result<usize> {View on GitHub (pinned to 88bb9c8533)
Solutions
- Pick a destination alias that does not exist or holds no memory rows.
- If the target data is disposable, purge it first (purge_agent on the target alias), then retry the rename.
- If both stores must survive, export_agent both aliases before renaming so nothing is lost.
Example fix
// before
memory.rename_agent("old-name", "writer").await?; // writer already has 42 rows
// after
let target = memory.export_agent("writer").await?;
if !target.is_empty() {
memory.purge_agent("writer").await?; // only if disposable
}
memory.rename_agent("old-name", "writer").await?; Defensive patterns
Strategy: validation
Validate before calling
// rename_agent refuses a non-empty target; check the same condition first
let target_rows = memory.export_agent(to).await?;
if !target_rows.is_empty() {
anyhow::bail!(
"target alias '{to}' already holds {} memory row(s); \
purge or pick another name",
target_rows.len()
);
}
memory.rename_agent(from, to).await?; Try / catch
match memory.rename_agent(from, to).await {
Ok(n) => Ok(n),
Err(e) if e.to_string().contains("refusing to merge") => {
// decide policy: pick another alias, or purge the target after backup
Err(e.context("rename target occupied; export/purge it first"))
}
Err(e) => Err(e),
} Prevention
- Check the destination alias with export_agent/count_agent before offering a rename in tooling — refuse occupied names in the UI.
- Back up both stores (export_agent) before any rename so a refused or mistaken merge attempt is always recoverable.
When it happens
Trigger: Calling rename_agent(from, to) when the destination alias `to` exists in the agents table and already owns at least one memory row — e.g. renaming to a retired agent's name that still has data.
Common situations: Reusing old agent names after reorganizations; retrying a rename after an earlier partial/manual attempt left rows; renaming onto an alias that a test or another agent populated.
Related errors
- Failed to atomically replace config file: {e}
- memory backend 'postgres' requested but this build was compi
- postgres backend requires storage config; call create_memory
- memory backend 'postgres' requires a `[storage.postgres.<ali
- {field_name} must not be empty
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/688453c3e632e296.
Report an issue: GitHub.