BloopAI/vibe-kanban · error · ContainerError
MsgStore not found for execution
Error message
MsgStore not found for execution
What it means
track_child_msgs_in_store looks up the in-memory MsgStore registered for the execution id and errors if none is registered. The store must exist because stdout/stderr streams are piped into it as LogMsg values. This is an internal lifecycle race: the child process exists but its message store was removed or never registered.
Source
Thrown at crates/local-deployment/src/container.rs:865
}
});
rx
}
fn dir_name_from_workspace(workspace_id: &Uuid, task_title: &str) -> String {
let task_title_id = git_branch_id(task_title);
format!("{}-{}", short_uuid(workspace_id), task_title_id)
}
async fn track_child_msgs_in_store(
&self,
id: Uuid,
child: &mut AsyncGroupChild,
) -> Result<(), ContainerError> {
let store = self
.get_msg_store_by_id(&id)
.await
.ok_or_else(|| ContainerError::Other(anyhow!("MsgStore not found for execution")))?;
let out = child.inner().stdout.take().expect("no stdout");
let err = child.inner().stderr.take().expect("no stderr");
// Map stdout bytes -> LogMsg::Stdout
let out = ReaderStream::new(out)
.map_ok(|chunk| LogMsg::Stdout(String::from_utf8_lossy(&chunk).into_owned()));
// Map stderr bytes -> LogMsg::Stderr
let err = ReaderStream::new(err)
.map_ok(|chunk| LogMsg::Stderr(String::from_utf8_lossy(&chunk).into_owned()));
// If you have a JSON Patch source, map it to LogMsg::JsonPatch too, then select all three.
// Merge and forward into the store
let merged = select(out, err); // Stream<Item = Result<LogMsg, io::Error>>
store.clone().spawn_forwarder(merged);
Ok(())
}View on GitHub (pinned to 4deb7eca8f)
Solutions
- Retry the execution — the race is usually transient.
- Ensure the MsgStore is registered for the execution id before spawning the child process.
- Check that stop/cancel paths only remove the store after the child is fully torn down.
- If reproducible, capture logs and report; it indicates a lifecycle-ordering bug in the execution manager.
Example fix
// before let spawned = executor_action.spawn(...).await??; self.track_child_msgs_in_store(id, &mut spawned.child).await?; // after self.ensure_msg_store(id).await; // register store first let spawned = executor_action.spawn(...).await??; self.track_child_msgs_in_store(id, &mut spawned.child).await?;
Defensive patterns
Strategy: retry
Validate before calling
// before spawning, confirm the store is registered
if container.get_msg_store_by_id(&id).await.is_none() {
container.register_msg_store(&id);
} Try / catch
match container.start_execution(...).await {
Err(ContainerError::Other(e)) if e.to_string().contains("MsgStore not found") => {
// transient race — retry once after re-registering the store
container.register_msg_store(&id);
container.start_execution(...).await
}
other => other,
} Prevention
- Register the MsgStore before spawning the child, always.
- Remove stores only after the child exits and streams are drained.
- Serialize stop/cancel with start to avoid startup races.
- Add an assertion/log when a store is missing to catch ordering bugs.
When it happens
Trigger: start_execution_inner spawning a child whose execution_process id has no MsgStore in the container's store map — e.g. store cleaned up concurrently, execution was cancelled, or the store was never inserted before spawn.
Common situations: Rapid stop/cancel of an execution racing with its startup; kill_all_running_processes clearing stores mid-spawn; internal bug where register/deregister ordering is wrong under load.
Related errors
- Failed to run setup script
- Failed to run cleanup script
- Channel not found
- Child process not found for execution
- MsgStore missing for execution {} during normalization setup
AI-assisted analysis of BloopAI/vibe-kanban@4deb7eca8f (2026-08-29).
Data as JSON: /api/errors/b7b46740eee115c9.
Report an issue: GitHub.