Hmbown/CodeWhale · error
Fleet task selects member whose role is , but worker.role…
Error message
Fleet task {} selects member {:?} whose role is {:?}, but worker.role names a different posture {:?}; a task has one posture — drop worker.role or select a member with that role What it means
A Fleet task both selects an explicit member and carries a legacy worker.role label naming a different posture. A task has exactly one posture; freeze_fleet_task_members rejects the contradiction instead of silently letting the write-capable legacy label widen the selection (issue #5945 context).
Solutions
- Drop the worker.role field from the task, keeping the member selection.
- Change the member selection to a member whose role matches the worker.role label.
- Update worker.role to the selected member's actual role.
Example fix
// before
"worker": {"member": "agent-1", "role": "impl"} // agent-1 is a reviewer
// after
"worker": {"member": "agent-1"} Defensive patterns
Strategy: validation
Validate before calling
fn posture_conflict(task: &Task, profile: &AgentProfile) -> bool { task.worker.as_ref().and_then(|w| w.role.as_deref()).map(|r| canonical_public_role_name(r) != profile.role).unwrap_or(false) } Prevention
- Clear worker.role when selecting a member explicitly
- Copy tasks without carrying stale role labels
- Treat member selection as the single source of posture
When it happens
Trigger: freeze_fleet_task_members where task.worker has both a member selector and a role label whose canonical_public_role_name differs from the selected member's role in the frozen snapshot.
Common situations: Editing a task's member without clearing the old role label; copying a task and swapping the member but not the role; older specs where the role field carried meaning it no longer does.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- An existing Fleet artifact contains different bytes
- agent profile cannot be empty
- agent profile must be a simple token
- agent profile may not disable approval_required
- agent profile may not request allow_shell=true
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/e0e53783e8af0829.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/fleet/worker_runtime.rs:228
};
if let Some(profile) = selected {
validate_selected_member_model(task, profile)?;
let snapshot = FrozenFleetMember::from_profile(profile);
// A task carries exactly one posture. When an explicit member
// selector is present, `worker.role` may only restate that
// member's role (any casing or legacy alias); naming a different
// posture is an authoring error, not a tie to arbitrate later.
// Failing closed here is what keeps the launch-time resolver
// honest: a read-only label can never widen to a member's write
// authority, and a member's read-only slot can never be widened by
// a write-capable label (#5945).
if explicit_selector.is_some()
&& let Some(label) = legacy_role_selector.as_deref()
{
let label = canonical_public_role_name(label);
if label != snapshot.role {
bail!(
"Fleet task {} selects member {:?} whose role is {:?}, but worker.role names a different posture {:?}; a task has one posture — drop worker.role or select a member with that role",
task.id,
profile.id,
snapshot.role,
label
);
}
}
task.metadata.insert(
FROZEN_FLEET_MEMBER_METADATA_KEY.to_string(),
serde_json::to_value(&snapshot)?,
);
let worker = task.worker.as_mut().expect("worker checked above");
worker.agent_profile = Some(format!("member:{}", profile.id));
if explicit_selector.is_none() {
worker.role = Some(snapshot.role.clone());
} else if let Some(role) = worker.role.as_mut() {
*role = canonical_public_role_name(role.trim());View on GitHub (pinned to 73e0f67d83)