tinyhumansai/openhuman · error · TeamError
unknown member: {member_id}
Error message
unknown member: {member_id} What it means
Thrown by the agent-team runtime's start entry point (agent_teams::runtime, exposed via the agent_teams start_member RPC) when run_ledger::get_agent_team_member cannot find the member id, or finds it but its team_id does not match the requested team. So a member that exists in a different team produces the same UnknownMember error as a nonexistent one. The check runs before the already-active guard and before any claim/state mutation.
Source
Thrown at src/openhuman/agent/orchestration/agent_teams/runtime.rs:89
/// could be dispatched: the task is already claimed, blocked on dependencies,
/// unknown, or the member has nothing claimable. An unknown member surfaces as
/// [`TeamError::UnknownMember`].
pub async fn start_member_run(
config: &Config,
team_id: &str,
member_id: &str,
task_id: Option<&str>,
model_override: Option<String>,
) -> Result<StartMemberOutcome> {
log::debug!(
target: LOG_TARGET,
"[agent_team_runtime] start.entry team={team_id} member={member_id} task={task_id:?}"
);
let member = run_ledger::get_agent_team_member(&config.workspace_dir, member_id)?
.filter(|m| m.team_id == team_id)
.ok_or_else(|| {
anyhow!(TeamError::UnknownMember {
member_id: member_id.to_string(),
})
})?;
// Reject a start on an already-active member before any claim or state
// mutation. The UI hides the control for active members, but this entry
// point is reachable directly over RPC; without this guard two near-
// simultaneous calls would each claim a task and the second
// `mark_agent_team_member_running` would clobber the first's task/run
// pointer, leaving two workers for one member.
if member.member_status == AgentTeamMemberStatus::Active {
log::debug!(
target: LOG_TARGET,
"[agent_team_runtime] start.reject_active team={team_id} member={member_id}"
);
return Ok(StartMemberOutcome::AlreadyActive);
}
View on GitHub (pinned to a221052e0d)
Solutions
- Fetch the team's members and start one whose id and team both match
- Confirm you are sending member_id (ledger id), not the agent definition id
- If the roster is stale, re-create the member before starting it
Example fix
// before
agent_teams::runtime::start(&config, &team_id, &member_id, task_id, model).await?;
// after — prove membership (and team match) before start
let member = run_ledger::get_agent_team_member(&config.workspace_dir, member_id)?
.filter(|m| m.team_id == team_id)
.with_context(|| format!("member {member_id} not in team {team_id}"))?;
agent_teams::runtime::start(&config, &team_id, &member.id, task_id, model).await?; Defensive patterns
Strategy: validation
Validate before calling
let member = run_ledger::get_agent_team_member(&config.workspace_dir, member_id)?
.filter(|m| m.team_id == team_id); // both existence AND team match
anyhow::ensure!(member.is_some(), "member {member_id} not in team {team_id}"); Type guard
fn member_in_team(config: &Config, team_id: &str, member_id: &str) -> bool {
run_ledger::get_agent_team_member(&config.workspace_dir, member_id)
.map_or(false, |m| m.map_or(false, |m| m.team_id == team_id))
} Try / catch
match agent_teams::runtime::start(&config, team_id, member_id, task_id, model).await {
Ok(o) => Ok(o),
Err(e) if e.to_string().starts_with("unknown member") => {
// re-list this team's members and start a live one instead
restart_latest_member(&config, team_id).await
}
Err(e) => Err(e),
} Prevention
- Namespace member ids per team in orchestrator state so cross-team reuse cannot happen
- Check both existence and team match — the runtime deliberately reports a wrong-team member as unknown
- Pass member_id from the create-team response; never synthesize one from an agent id
When it happens
Trigger: Calling start_member with a member id from another team, a stale/removed member id, or a typo. Because of the .filter(|m| m.team_id == team_id), pairing a valid member id with the wrong team_id also triggers it.
Common situations: Orchestrator interleaving ids from multiple concurrent teams; UI roster not refreshed after team re-creation; passing agent_id where member_id is expected.
Related errors
- agentTeamApi: ${label} must be a positive integer
- agentTeamApi.get: teamId is required
- agentTeamApi.listMessages: teamId is required
- agentTeamApi.completeTask: teamId, taskId and memberId are r
- agentTeamApi.shutdownMember: teamId and memberId are require
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/660b9381601f34cb.
Report an issue: GitHub.