tinyhumansai/openhuman · error

definition {} no longer exists

Error message

definition {} no longer exists

What it means

Thrown by workflow_runs::engine::resume_workflow_run when the run row exists but definition_by_id(run.definition_id) no longer resolves — the builtin workflow definition the run was started under is not offered by the current binary. Definitions are compiled-in builtins, so this is version drift between the run's creation and the resume attempt.

Source

Thrown at src/openhuman/agent/orchestration/workflow_runs/engine.rs:300

/// Resume an interrupted (or otherwise incomplete) workflow run.
///
/// Reloads the run, clears any stale cancellation flag, flips the row back to
/// `Running`, and spawns a fresh engine loop. Phases already `completed` in
/// `phase_states` are skipped; the loop continues from the first incomplete
/// phase whose dependencies are satisfied. Returns the run row (now `Running`),
/// or an error if the run is unknown / already terminal-complete / its
/// definition no longer exists.
pub async fn resume_workflow_run(config: &Config, id: &str) -> Result<WorkflowRun> {
    log::debug!(target: LOG_TARGET, "[workflow_run_engine] resume.entry run={id}");
    let run = get_workflow_run(&config.workspace_dir, id)?
        .ok_or_else(|| anyhow!("unknown workflow run: {id}"))?;

    if matches!(run.status, WorkflowRunStatus::Completed) {
        return Err(anyhow!("workflow run {id} is already completed"));
    }

    let definition = definition_by_id(&run.definition_id)
        .ok_or_else(|| anyhow!("definition {} no longer exists", run.definition_id))?;

    // Clear any prior cancellation intent and re-register a fresh flag.
    clear_cancel_flag(id);
    register_cancel_flag(id);

    let resumed = upsert_workflow_run(
        &config.workspace_dir,
        WorkflowRunUpsert {
            id: run.id.clone(),
            definition_id: run.definition_id.clone(),
            parent_thread_id: run.parent_thread_id.clone(),
            input: run.input.clone(),
            phase_states: run.phase_states.clone(),
            child_run_ids: run.child_run_ids.clone(),
            status: WorkflowRunStatus::Running,
            summary: run.summary.clone(),
            started_at: Some(run.started_at),
            completed_at: None,

View on GitHub (pinned to a221052e0d)

Solutions

  1. Start a fresh run with a definition id from the current list_definitions instead of resuming
  2. Clean up / archive runs whose definition_id no longer resolves so they stop appearing resumable
  3. Keep builtin definition ids stable across releases if old runs must remain resumable

Example fix

// before
resume_workflow_run(&config, &run_id).await?; // fails: definition gone after upgrade

// after — verify the definition still exists, else restart from scratch
let run = get_workflow_run(&config.workspace_dir, &run_id)?.context("unknown run")?;
let resumed = match workflow_runs::ops::definition_by_id(&run.definition_id) {
    Some(_) => resume_workflow_run(&config, &run_id).await?,
    None => start_workflow_run(&config, &current_definition_id, run.input.clone(), run.parent_thread_id).await?,
};
Defensive patterns

Strategy: validation

Validate before calling

let run = get_workflow_run(&config.workspace_dir, run_id)?.context("unknown run")?;
if workflow_runs::ops::definition_by_id(&run.definition_id).is_none() {
    // definition gone in this build — restart with a current definition instead of resuming
}

Type guard

fn definition_still_available(definition_id: &str) -> bool {
    workflow_runs::ops::definition_by_id(definition_id).is_some()
}

Try / catch

match resume_workflow_run(&config, run_id).await {
    Ok(r) => Ok(r),
    Err(e) if e.to_string().contains("no longer exists") => {
        start_workflow_run(&config, &current_definition_id, run.input.clone(), run.parent_thread_id).await
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Starting a run on one core version, upgrading (or switching to a build where the builtin was renamed/removed), then resuming the persisted run. Also reproducible by manually editing a run row's definition_id.

Common situations: App auto-update between an interrupted run and a later resume; resuming old runs after a dev iteration that changed builtin definitions; mixed-version fleet where runs migrate between builds.

Related errors


AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16). Data as JSON: /api/errors/efbef185f8860137. Report an issue: GitHub.