MemPalace/mempalace · error · ValueError
event {event_id!r} not found
Error message
event {event_id!r} not found What it means
ack_event(event_id=...) could not find an event with that id in the events table, so no acknowledgment can be created. The ack mechanism copies stream/room/correlation_id from the target event and routes back to its from_agent — with no target there is nothing to copy, hence the hard failure. The id is first normalized through _sanitize_routing (trim, length, control chars).
Source
Thrown at mempalace/logstream.py:595
from_agent: str,
status: str = None,
body: str = "",
) -> dict:
"""Append an ``event.ack`` referencing a prior event.
The target event is never mutated. The ack copies the target's
stream/room, copies its ``correlation_id`` (falling back to the
target's id so request/ack stay tied together), and routes back
to the target's ``from_agent``.
"""
event_id = _sanitize_routing(event_id, "event_id")
with self._lock:
conn = self._conn()
target = conn.execute(
"SELECT rowid, * FROM events WHERE id = ?", (event_id,)
).fetchone()
if target is None:
raise ValueError(f"event {event_id!r} not found")
return self.append_event(
type=ACK_EVENT_TYPE,
stream=target["stream"],
room=target["room"],
from_agent=from_agent,
to_agent=target["from_agent"],
correlation_id=target["correlation_id"] or target["id"],
status=status,
body=body,
metadata={"ack_of": event_id},
)
def submit_patch(
self,
content: str,
from_agent: str,
stream: str,View on GitHub (pinned to 06cb6987f0)
Solutions
- Use the id exactly as returned: evt = ls.append_event(...) then later ls.ack_event(evt['id'], ...).
- Confirm the id exists first: ls.get_event(event_id) or ls.list_events(since_event_id=...) to see what is visible.
- Ensure producer and consumer open the same database file (same palace directory) — replication must deliver the original event before acking.
Example fix
// before
ls.ack_event("evt_20250814", from_agent="windows-codex") # truncated id
// after
evt = ls.list_events(type="task.request", correlation_id="task_123")[0]
ls.ack_event(evt["id"], from_agent="windows-codex", body="started") Defensive patterns
Strategy: try-catch
Validate before calling
def event_exists(ls, event_id) -> bool:
try:
return ls.get_event(event_id) is not None
except ValueError:
return False
if not event_exists(ls, target_id):
raise LookupError(f"cannot ack unknown event {target_id!r}; not yet replicated?") Try / catch
try:
ack = ls.ack_event(event_id, from_agent=me, body=body)
except ValueError as e:
if "not found" in str(e):
# target not replicated/visible yet — schedule a retry after sync
retry_later(event_id, from_agent=me, body=body)
else:
raise Prevention
- Carry the full 'evt_...' id from the append_event return value — never retype or truncate it.
- In replicated deployments, ack only events fetched from the same database you ack into.
- Treat ack-not-found as an expected sync race: retry with backoff instead of crashing the agent.
When it happens
Trigger: ack_event with a typo'd or truncated id string; acking an event that lives in a different db_path/palace directory; acking an event that was never appended (producer and consumer disagree on the exchange); passing rowid instead of the 'evt_...' string id.
Common situations: Multi-replica setups where the consumer's logstream has not yet replicated the original event; ids mangled through log truncation or clipboard copy; tests against a fresh in-memory Logstream without seeding the target event.
Related errors
- since_event_id {since_event_id!r} not found
- unknown job id: {job_id}
- {field_name} must be a non-empty string
- {field_name} exceeds maximum length of {_MAX_ROUTING_LENGTH}
- {field_name} contains control characters
AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15).
Data as JSON: /api/errors/2dc8ffc7612d9667.
Report an issue: GitHub.