tinyhumansai/openhuman · error · TeamError
task {task_id} cannot depend on itself
Error message
task {task_id} cannot depend on itself What it means
Thrown by agent_teams::ops::validate_dependencies (reached via assign_task) when a new task's depends_on list contains the new task's own id. Self-dependency is rejected before any ledger write; it wraps TeamError::SelfDependency.
Source
Thrown at src/openhuman/agent/orchestration/agent_teams/ops.rs:404
})
}
/// Validate a new task's dependency edges against the team's existing tasks.
///
/// 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 tasksView on GitHub (pinned to a221052e0d)
Solutions
- Filter the new task's own id out of depends_on before submitting
- Check the code/template that builds depends_on for an id-variable mix-up
- Use distinct, meaningful task ids so deps never collide by construction
Example fix
// before let depends_on = vec![task_id.clone()]; // self-dep -> error agent_teams::ops::assign_task(&config, &team_id, &task_id, member_id, &depends_on)?; // after — strip self-reference before submit let depends_on: Vec<String> = depends_on.into_iter().filter(|d| d != &task_id).collect(); agent_teams::ops::assign_task(&config, &team_id, &task_id, member_id, &depends_on)?;
Defensive patterns
Strategy: validation
Validate before calling
let depends_on: Vec<String> = depends_on
.into_iter()
.filter(|d| d != &new_task_id)
.collect(); // strip self-reference before assign_task Type guard
fn has_self_dependency(new_task_id: &str, depends_on: &[String]) -> bool {
depends_on.iter().any(|d| d == new_task_id)
} Prevention
- Generate task ids and dependency lists from distinct variables so a template can never echo the id into its own deps
- Validate depends_on client-side (no self-ref, all ids known) before every assign_task
- Prefer unique, descriptive task ids over sequential ones that are easy to alias
When it happens
Trigger: Calling agent_teams assign_task with depends_on containing the very task_id being created — typically a template that interpolates the new id into its own dependency list, or a copy-paste of an existing task's deps onto a task renamed to a dep's id.
Common situations: Generated task graphs where the id and dep id come from the same variable; renaming a task to match one of its dependencies; LLM-authored dependency lists echoing the task id.
Related errors
- unknown dependency: {depends_on}
- dependency cycle detected
- agentTeamApi: ${label} must be a positive integer
- agentTeamApi.get: teamId is required
- agentTeamApi.listMessages: teamId is required
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/f83a4ce6de8fae40.
Report an issue: GitHub.