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

  1. Fetch the team's members and start one whose id and team both match
  2. Confirm you are sending member_id (ledger id), not the agent definition id
  3. 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

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


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