clash-verge-rev/clash-verge-rev · critical · anyhow::Error

core did not become ready after start

Error message

core did not become ready after start

What it means

Thrown by run_core_start_transition after the start_core future succeeds but the core_is_ready predicate returns false. The core process was spawned but did not reach readiness (e.g. mihomo API not responding on external-controller, health probe failed) within the transition's expectations.

Source

Thrown at src-tauri/src/core/manager/lifecycle.rs:158

    }
    Ok(())
}

async fn run_ready_core_start_transition<Start, StartFuture, Ready, Apply, ApplyFuture>(
    start_core: Start,
    core_is_ready: Ready,
    apply_proxy: Apply,
) -> Result<()>
where
    Start: FnOnce() -> StartFuture,
    StartFuture: std::future::Future<Output = Result<()>>,
    Ready: FnOnce() -> bool,
    Apply: FnOnce() -> ApplyFuture,
    ApplyFuture: std::future::Future<Output = Result<()>>,
{
    start_core().await?;
    if !core_is_ready() {
        anyhow::bail!("core did not become ready after start");
    }
    apply_proxy().await
}

async fn run_sidecar_termination_transition<Clear, ClearFuture, Terminate>(
    clear_proxy: Clear,
    terminate_sidecar: Terminate,
) -> Result<()>
where
    Clear: FnOnce() -> ClearFuture,
    ClearFuture: std::future::Future<Output = Result<()>>,
    Terminate: FnOnce(),
{
    clear_proxy().await?;
    terminate_sidecar();
    Ok(())
}

View on GitHub (pinned to 5cad0f2799)

Solutions

  1. Check that no other mihomo/proxy process is holding external-controller's port.
  2. Inspect mihomo's stdout/stderr log for the startup error that prevented readiness.
  3. Confirm `external-controller` and `secret` in the runtime config are reachable.
  4. Increase startup patience or retry the start after clearing the conflicting process.
  5. Validate the runtime config offline with `mihomo -t`.
Defensive patterns

Strategy: retry

Try / catch

for attempt in 0..3 {
    match run_core_start_transition(start, ready, apply).await {
        Ok(_) => break,
        Err(e) if e.to_string().contains("did not become ready") && attempt < 2 => {
            kill_orphan_on_port().await; continue;
        }
        Err(e) => return Err(e),
    }
}

Prevention

When it happens

Trigger: start_core_inner returned Ok but the readiness check (typically an HTTP probe to the mihomo external-controller) still reports the core as not running; mihomo started but is stuck on initialization (port conflict, slow GeoIP download, bad config loaded after spawn).

Common situations: external-controller port is already taken by another instance; mihomo is downloading a large GeoIP/database file on first run; the API bind address is wrong (e.g. set to an interface that doesn't exist); startup raced ahead of readiness because the process forked but exited immediately after.

Related errors


AI-assisted analysis of clash-verge-rev/clash-verge-rev@5cad0f2799 (2026-08-12). Data as JSON: /api/errors/623bdc406c6dce58. Report an issue: GitHub.