xai-org/grok-build · error · std::io::Error
workflow state has no registered resume source
Error message
workflow state has no registered resume source
What it means
persist_now writes workflow state synchronously but first requires a registered resume source via manifest_for; if the WorkflowRunState's run_id was never registered (or the store was reloaded without re-registration), it returns io::ErrorKind::NotFound "workflow state has no registered resume source". State cannot be persisted without knowing how to resume the run.
Source
Thrown at crates/codegen/xai-grok-shell/src/session/workflow/store.rs:178
Ok(())
}
fn manifest_for(&self, state: &WorkflowRunState) -> Option<WorkflowRunManifest> {
let revision = self
.sources
.lock()
.get(&state.run_id)
.map(|source| source.revision)?;
Some(WorkflowRunManifest {
version: WORKFLOW_RUN_MANIFEST_VERSION,
state: state.clone(),
script_revision: revision,
})
}
pub(crate) fn persist_now(&self, state: &WorkflowRunState) -> io::Result<()> {
let Some(manifest) = self.manifest_for(state) else {
return Err(io::Error::new(
io::ErrorKind::NotFound,
"workflow state has no registered resume source",
));
};
let Some(run_dir) = self.run_dir(&state.run_id) else {
return Ok(());
};
let json = serde_json::to_vec_pretty(&manifest).map_err(io::Error::other)?;
atomic_write_replace(&run_dir.join("state.json"), &json)
}
pub(crate) fn persist(&self, state: &WorkflowRunState) -> io::Result<()> {
let manifest = self.manifest_for(state).ok_or_else(|| {
io::Error::new(
io::ErrorKind::NotFound,
"workflow state has no registered resume source",
)
})?;View on GitHub (pinned to bc7f02eddd)
Solutions
- Call register(run_id, script, args, effort) before persist_now
- Ensure the resume/restore path re-registers sources before any persistence
- Verify the run_id in the state matches the one registered (no id mismatch)
- If persistence is optional for this run, skip persist_now instead of propagating the error
Example fix
// before store.persist_now(&state)?; // NotFound after reload // after store.register(&state.run_id, &script, &args, effort)?; store.persist_now(&state)?;
Defensive patterns
Strategy: validation
Validate before calling
if store.source(&state.run_id).is_none() {
store.register(&state.run_id, &script, &args, effort)?;
}
store.persist_now(&state)?; Type guard
fn can_persist(store: &WorkflowStore, state: &WorkflowRunState) -> bool {
store.source(&state.run_id).is_some()
} Try / catch
match store.persist_now(&state) {
Err(e) if e.kind() == io::ErrorKind::NotFound
&& e.to_string().contains("resume source") => {
store.register(&state.run_id, &script, &args, effort)?;
store.persist_now(&state)?;
}
other => other?,
} Prevention
- Re-register all sources immediately after reloading/restarting the store
- Keep one owner responsible for the register-before-persist ordering
- Assert run_id consistency between registered sources and state objects
- Add a debug check/log when persisting a state with no registered source
When it happens
Trigger: Calling persist_now with a WorkflowRunState whose run_id has no entry in the store's sources map — e.g. after process restart/reload without re-registering, or persisting a state constructed for an unregistered run.
Common situations: Restoring state from disk after a crash but resuming before re-registering the script/args; a bug where register was skipped on a fast-fail path; persisting a stale state object from a previous session.
Related errors
- memory directory {:?} does not exist: {e}
- NotFound
- Compaction checkpoint file missing: {checkpoint_path}. Canno
- workflow source already registered: {run_id}
- session '{name}' not found
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/87454aa53f6dcb6a.
Report an issue: GitHub.