tinyhumansai/openhuman · error · TeamError

unknown dependency: {depends_on}

Error message

unknown dependency: {depends_on}

What it means

Thrown by agent_teams::ops::validate_dependencies (via assign_task) when a depends_on entry does not match the id of any existing task in the team. Dependencies must reference tasks already created in the same team; unknown ids abort the assignment before the ledger write. It wraps TeamError::UnknownDependency, carrying the offending dep id.

Source

Thrown at src/openhuman/agent/orchestration/agent_teams/ops.rs:409

/// Rejects self-dependency, unknown dependency ids, and any edge that would
/// introduce a cycle. The cycle check builds the full graph (existing tasks +
/// the new task with its proposed deps) and runs Kahn's algorithm — the same
/// shape used for workflow phase graphs in `workflow_runs::ops::has_cycle`.
fn validate_dependencies(
    new_task_id: &str,
    depends_on: &[String],
    existing: &[AgentTeamTask],
) -> Result<()> {
    let known: HashSet<&str> = existing.iter().map(|t| t.id.as_str()).collect();

    for dep in depends_on {
        if dep == new_task_id {
            return Err(anyhow!(TeamError::SelfDependency {
                task_id: new_task_id.to_string(),
            }));
        }
        if !known.contains(dep.as_str()) {
            return Err(anyhow!(TeamError::UnknownDependency {
                depends_on: dep.clone(),
            }));
        }
    }

    if has_task_cycle(new_task_id, depends_on, existing) {
        return Err(anyhow!(TeamError::CyclicDependency));
    }

    Ok(())
}

/// Kahn's-algorithm cycle check over the task dependency graph (existing tasks
/// plus the candidate new task). Edge `dep -> task` means `task` depends on
/// `dep`. Edges pointing at unknown ids are ignored here (rejected separately).
fn has_task_cycle(
    new_task_id: &str,
    new_depends_on: &[String],

View on GitHub (pinned to a221052e0d)

Solutions

  1. Create dependency tasks first and await each success before tasks that reference them
  2. Cross-check depends_on against the team's task list (agent_teams get) before submitting
  3. Trim/normalize ids and verify they belong to the same team_id

Example fix

// before
agent_teams::ops::assign_task(&config, &team_id, &new_id, member, &["reseach-1".into()])?; // typo

// after — validate deps against the live task list
let tasks = run_ledger::list_agent_team_tasks(&config.workspace_dir, team_id)?;
let known: HashSet<&str> = tasks.iter().map(|t| t.id.as_str()).collect();
let deps: Vec<String> = depends_on.into_iter().filter(|d| known.contains(d.as_str())).collect();
agent_teams::ops::assign_task(&config, &team_id, &new_id, member, &deps)?;
Defensive patterns

Strategy: validation

Validate before calling

let tasks = run_ledger::list_agent_team_tasks(&config.workspace_dir, team_id)?;
let known: HashSet<&str> = tasks.iter().map(|t| t.id.as_str()).collect();
anyhow::ensure!(depends_on.iter().all(|d| known.contains(d.as_str())), "unknown dependency");

Type guard

fn deps_are_known(existing: &[AgentTeamTask], depends_on: &[String]) -> bool {
    let known: HashSet<&str> = existing.iter().map(|t| t.id.as_str()).collect();
    depends_on.iter().all(|d| known.contains(d.as_str()))
}

Prevention

When it happens

Trigger: Calling assign_task with a dep id that is not in the team's existing task list — dependency task not yet created, created in a different team, a typo, or the dep task's creation failed earlier in a batch.

Common situations: Batch task creation that does not wait for each assign_task to persist before referencing the next; refactoring that moved tasks between teams; trailing whitespace or case differences in dep ids.

Related errors


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