{"record":{"id":"660b9381601f34cb","repo":"tinyhumansai/openhuman","slug":"unknown-member-member-id-660b93","errorCode":null,"errorMessage":"unknown member: {member_id}","messagePattern":"unknown member: (.+?)","errorType":"validation","errorClass":"TeamError","httpStatus":null,"severity":"error","filePath":"src/openhuman/agent/orchestration/agent_teams/runtime.rs","lineNumber":89,"sourceCode":"/// could be dispatched: the task is already claimed, blocked on dependencies,\n/// unknown, or the member has nothing claimable. An unknown member surfaces as\n/// [`TeamError::UnknownMember`].\npub async fn start_member_run(\n    config: &Config,\n    team_id: &str,\n    member_id: &str,\n    task_id: Option<&str>,\n    model_override: Option<String>,\n) -> Result<StartMemberOutcome> {\n    log::debug!(\n        target: LOG_TARGET,\n        \"[agent_team_runtime] start.entry team={team_id} member={member_id} task={task_id:?}\"\n    );\n\n    let member = run_ledger::get_agent_team_member(&config.workspace_dir, member_id)?\n        .filter(|m| m.team_id == team_id)\n        .ok_or_else(|| {\n            anyhow!(TeamError::UnknownMember {\n                member_id: member_id.to_string(),\n            })\n        })?;\n\n    // Reject a start on an already-active member before any claim or state\n    // mutation. The UI hides the control for active members, but this entry\n    // point is reachable directly over RPC; without this guard two near-\n    // simultaneous calls would each claim a task and the second\n    // `mark_agent_team_member_running` would clobber the first's task/run\n    // pointer, leaving two workers for one member.\n    if member.member_status == AgentTeamMemberStatus::Active {\n        log::debug!(\n            target: LOG_TARGET,\n            \"[agent_team_runtime] start.reject_active team={team_id} member={member_id}\"\n        );\n        return Ok(StartMemberOutcome::AlreadyActive);\n    }\n","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/src/openhuman/agent/orchestration/agent_teams/runtime.rs#L71-L107","documentation":"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.","triggerScenarios":"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.","commonSituations":"Orchestrator interleaving ids from multiple concurrent teams; UI roster not refreshed after team re-creation; passing agent_id where member_id is expected.","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"],"exampleFix":"// before\nagent_teams::runtime::start(&config, &team_id, &member_id, task_id, model).await?;\n\n// after — prove membership (and team match) before start\nlet member = run_ledger::get_agent_team_member(&config.workspace_dir, member_id)?\n    .filter(|m| m.team_id == team_id)\n    .with_context(|| format!(\"member {member_id} not in team {team_id}\"))?;\nagent_teams::runtime::start(&config, &team_id, &member.id, task_id, model).await?;","handlingStrategy":"validation","validationCode":"let member = run_ledger::get_agent_team_member(&config.workspace_dir, member_id)?\n    .filter(|m| m.team_id == team_id); // both existence AND team match\nanyhow::ensure!(member.is_some(), \"member {member_id} not in team {team_id}\");","typeGuard":"fn member_in_team(config: &Config, team_id: &str, member_id: &str) -> bool {\n    run_ledger::get_agent_team_member(&config.workspace_dir, member_id)\n        .map_or(false, |m| m.map_or(false, |m| m.team_id == team_id))\n}","tryCatchPattern":"match agent_teams::runtime::start(&config, team_id, member_id, task_id, model).await {\n    Ok(o) => Ok(o),\n    Err(e) if e.to_string().starts_with(\"unknown member\") => {\n        // re-list this team's members and start a live one instead\n        restart_latest_member(&config, team_id).await\n    }\n    Err(e) => Err(e),\n}","preventionTips":["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"],"tags":["agent-teams","runtime","member-id","validation"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}