stalwartlabs/stalwart · error
Incorrect number of task channels
Error message
Incorrect number of task channels
What it means
The spawned TaskManager IPC worker expects the vector of task channels to convert into a fixed-size array via `try_into()`. This panic fires when the number of channels does not match the expected fixed count (TaskIpc count), which would be an internal bug — the channel vector was built with a different length than the array type expects.
Source
Thrown at crates/services/src/task_manager/manager.rs:296
err.id(job.id)
.details("Failed to retrieve task details.")
.caused_by(trc::location!())
);
}
}
if refresh_queue || rx.is_empty() {
server.notify_task_queue();
}
}
});
}
}
const REFRESH_INTERVAL: Duration = Duration::from_secs(60);
tokio::spawn(async move {
let mut ipc = TaskManagerIpc {
txs: txs.try_into().expect("Incorrect number of task channels"),
locked: Default::default(),
revision: 0,
};
let rx = inner.ipc.task_tx.clone();
loop {
// Index any queued tasks
let mut sleep_for = inner.build_server().process_tasks(&mut ipc).await;
if is_clustered && sleep_for > REFRESH_INTERVAL {
sleep_for = REFRESH_INTERVAL;
}
// Wait for a signal or sleep until the next task is due
let _ = tokio::time::timeout(sleep_for, rx.notified()).await;
}
});
}
pub(crate) trait TaskQueueManager: Sync + Send {View on GitHub (pinned to e962003857)
Solutions
- Update the expected channel count / array type in TaskManagerIpc to match the number of spawned task channels
- Check the code that builds `txs` and ensure every task type registers exactly one channel
- Add a length assertion when building `txs` to fail fast with a clearer message
Example fix
// before
let ipc = TaskManagerIpc {
txs: txs.try_into().expect("Incorrect number of task channels"),
// after
assert_eq!(txs.len(), NUM_TASK_TYPES, "task channel count mismatch");
let ipc = TaskManagerIpc {
txs: txs.try_into().unwrap(), Defensive patterns
Strategy: validation
Validate before calling
assert_eq!(txs.len(), EXPECTED_TASK_CHANNEL_COUNT, "Incorrect number of task channels");
Type guard
fn is_expected_count(txs: &[Sender<Task>]) -> bool { txs.len() == EXPECTED_TASK_CHANNEL_COUNT } Try / catch
let Ok(arr) = <[...; N]>::try_into(txs) else {
panic!("task channel count mismatch: got {}, want {}", txs.len(), N);
}; Prevention
- Derive the channel count from a single constant shared by producer and consumer
- Add a unit test asserting the number of registered task types matches the fixed array size
- When adding a task type, update both registration and the TaskManagerIpc array type
When it happens
Trigger: An internal invariant violation: the number of task senders collected into `txs` differs from the fixed array size expected by TaskManagerIpc, typically after adding/removing a task type in one place but not the other.
Common situations: Developers adding a new task/subsystem to the task manager without updating the fixed channel count; merging partial refactors of the task registry.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
AI-assisted analysis of stalwartlabs/stalwart@e962003857 (2026-09-06).
Data as JSON: /api/errors/acdae31ee346d4f1.
Report an issue: GitHub.