libnyanpasu/clash-nyanpasu · error
effect function failed: {e:#?}
Error message
effect function failed: {e:#?} What it means
In with_pending_state_inner, the effect function of a pending state transaction failed, so the coordinator rolls back the transaction (RollbackReason::CoordinatorError) and returns the original error. The message wraps the effect error for the rollback record.
Source
Thrown at backend/nyanpasu-core/src/state/coordinator.rs:380
},
None => effect_fn(new_state).await.map_err(WithEffectError::Effect),
};
match effect_result {
Ok(result) => {
if tx.commit().await.is_err() {
let actual = self.sync_change_id_after_cas_mismatch();
return Err(WithEffectError::State(
StateChangedError::StateCasMismatch {
expected: current_state.version,
actual,
},
));
}
self.mark_change_id_committed(next_changed_id);
Ok((result, report))
}
Err(e) => {
tx.rollback(RollbackReason::CoordinatorError(Arc::new(anyhow!(
"effect function failed: {e:#?}"
))))
.await;
Err(e)
}
}
}
}
// -- Builder --
pub struct StateCoordinatorBuilder<T: Clone + Send + Sync + 'static> {
notify_strategy: NotifyStrategy,
subscribers: IndexMap<SubscriberName<'static>, ArcStateSubscriber<T>>,
}
impl<T: Clone + Send + Sync + 'static> Default for StateCoordinatorBuilder<T> {
fn default() -> Self {View on GitHub (pinned to f7dbce2997)
Solutions
- Read the wrapped inner error to find the actual failing effect step.
- Retry the operation once the underlying cause (core down, disk error) is resolved; state was rolled back so it is safe to redo.
- Move fragile side effects out of the effect closure or make them idempotent.
- Use with_pending_state_timeout with a generous timeout if the effect is slow rather than failing.
Example fix
// before
coordinator.with_pending_state(|tx| async {
restart_core().await?; // failure rolls everything back
Ok(())
})
// after
coordinator.with_pending_state(|tx| async {
if let Err(e) = restart_core().await {
log::error!("core restart failed, state kept: {e}"); // report degraded, don't fail effect
}
Ok(())
}) Defensive patterns
Strategy: retry
Validate before calling
// pre-check downstream dependencies before running the effect
async fn can_run_effect() -> bool {
core_client.ping().await.is_ok() && config_dir_writable()
} Try / catch
match coordinator.with_pending_state(effect_fn).await {
Err(e) => {
log::error!("effect failed, transaction rolled back: {e:#}");
// state is consistent; fix cause and retry
retry_with_backoff(|| coordinator.with_pending_state(effect_fn)).await
}
Ok(v) => v,
} Prevention
- Ensure the core/actors the effect calls are healthy before committing state
- Avoid synchronous cross-actor cycles inside effects
- Make effects idempotent and log the full error chain for diagnosis
When it happens
Trigger: Calling with_pending_state / with_pending_state_timeout where the post-prepare effect_fn fails — e.g. runtime config generation, core restart, or IPC side effect returns Err.
Common situations: Core process unavailable during a config patch, filesystem errors writing generated config, or timeouts in downstream actor calls triggered from the effect.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- effect function failed: {error:#?}
- compensation fenced by diverged target at {}
- state transaction dropped before commit or rollback complete
- IPC server is already initialized
- cannot cancel an activated cleanup operation
AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08).
Data as JSON: /api/errors/38cfb346839640e6.
Report an issue: GitHub.