{"record":{"id":"b7b46740eee115c9","repo":"BloopAI/vibe-kanban","slug":"msgstore-not-found-for-execution","errorCode":null,"errorMessage":"MsgStore not found for execution","messagePattern":"MsgStore not found for execution","errorType":"exception","errorClass":"ContainerError","httpStatus":null,"severity":"error","filePath":"crates/local-deployment/src/container.rs","lineNumber":865,"sourceCode":"            }\n        });\n        rx\n    }\n\n    fn dir_name_from_workspace(workspace_id: &Uuid, task_title: &str) -> String {\n        let task_title_id = git_branch_id(task_title);\n        format!(\"{}-{}\", short_uuid(workspace_id), task_title_id)\n    }\n\n    async fn track_child_msgs_in_store(\n        &self,\n        id: Uuid,\n        child: &mut AsyncGroupChild,\n    ) -> Result<(), ContainerError> {\n        let store = self\n            .get_msg_store_by_id(&id)\n            .await\n            .ok_or_else(|| ContainerError::Other(anyhow!(\"MsgStore not found for execution\")))?;\n        let out = child.inner().stdout.take().expect(\"no stdout\");\n        let err = child.inner().stderr.take().expect(\"no stderr\");\n\n        // Map stdout bytes -> LogMsg::Stdout\n        let out = ReaderStream::new(out)\n            .map_ok(|chunk| LogMsg::Stdout(String::from_utf8_lossy(&chunk).into_owned()));\n\n        // Map stderr bytes -> LogMsg::Stderr\n        let err = ReaderStream::new(err)\n            .map_ok(|chunk| LogMsg::Stderr(String::from_utf8_lossy(&chunk).into_owned()));\n\n        // If you have a JSON Patch source, map it to LogMsg::JsonPatch too, then select all three.\n\n        // Merge and forward into the store\n        let merged = select(out, err); // Stream<Item = Result<LogMsg, io::Error>>\n        store.clone().spawn_forwarder(merged);\n        Ok(())\n    }","sourceCodeStart":847,"sourceCodeEnd":883,"githubUrl":"https://github.com/BloopAI/vibe-kanban/blob/4deb7eca8f381f7cbc1f9d15515a9ab8f8009053/crates/local-deployment/src/container.rs#L847-L883","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nlet spawned = executor_action.spawn(...).await??;\nself.track_child_msgs_in_store(id, &mut spawned.child).await?;\n// after\nself.ensure_msg_store(id).await; // register store first\nlet spawned = executor_action.spawn(...).await??;\nself.track_child_msgs_in_store(id, &mut spawned.child).await?;","handlingStrategy":"retry","validationCode":"// before spawning, confirm the store is registered\nif container.get_msg_store_by_id(&id).await.is_none() {\n    container.register_msg_store(&id);\n}","typeGuard":null,"tryCatchPattern":"match container.start_execution(...).await {\n    Err(ContainerError::Other(e)) if e.to_string().contains(\"MsgStore not found\") => {\n        // transient race — retry once after re-registering the store\n        container.register_msg_store(&id);\n        container.start_execution(...).await\n    }\n    other => other,\n}","preventionTips":["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."],"tags":["execution","lifecycle","race-condition"],"backgroundTag":"execution-store-missing","analyzedSha":"4deb7eca8f381f7cbc1f9d15515a9ab8f8009053","analyzedAt":"2026-08-29T09:24:13.446Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}