BloopAI/vibe-kanban · error · ContainerError

Timeout: process took more than 30 seconds to start

Error message

Timeout: process took more than 30 seconds to start

What it means

start_execution_inner wraps executor_action.spawn in a 30-second tokio timeout; if the executor process does not spawn within that window the future is dropped and this timeout error is returned. This prevents hangs from blocked executors (e.g. waiting on network or approval) from stalling executions indefinitely.

Source

Thrown at crates/local-deployment/src/container.rs:1376

        drop(config);
        let mut env = ExecutionEnv::new(
            repo_context,
            commit_reminder_enabled,
            commit_reminder_prompt,
        );

        // Always inject workspace/session context
        env.insert("VK_WORKSPACE_ID", workspace.id.to_string());
        env.insert("VK_WORKSPACE_BRANCH", &workspace.branch);

        // Create the child and stream, add to execution tracker with timeout
        let mut spawned = tokio::time::timeout(
            Duration::from_secs(30),
            executor_action.spawn(&current_dir, approvals_service, &env),
        )
        .await
        .map_err(|_| {
            ContainerError::Other(anyhow!(
                "Timeout: process took more than 30 seconds to start"
            ))
        })??;

        if let Err(e) = self
            .track_child_msgs_in_store(execution_process.id, &mut spawned.child)
            .await
        {
            let _ = command::kill_process_group(&mut spawned.child).await;
            return Err(e);
        }

        self.add_child_to_store(execution_process.id, spawned.child)
            .await;

        // Store cancellation token for graceful shutdown
        if let Some(cancel) = spawned.cancel {
            self.add_cancellation_token(execution_process.id, cancel)

View on GitHub (pinned to 4deb7eca8f)

Solutions

  1. Retry — transient slowness (network, cold cache) often resolves on a second attempt.
  2. Pre-install/warm the executor binary so spawn does not need to download it.
  3. Check network/proxy settings if the executor fetches assets at startup.
  4. Run the executor command manually in the worktree to see what it is blocking on.

Example fix

// before
// spawn hangs 45s on first run downloading the executor
// after
executors::ensure_executor_installed(&action).await?; // warm cache before spawn
let spawned = tokio::time::timeout(Duration::from_secs(30), action.spawn(...)).await??;
Defensive patterns

Strategy: retry

Validate before calling

// ensure the executor binary is available before spawning
if !executor_binary_cached(&action).await? {
    executors::install_executor(&action).await?;
}

Try / catch

match container.start_execution(...).await {
    Err(ContainerError::Other(e)) if e.to_string().contains("Timeout: process took more than 30 seconds") => {
        // one retry after warming caches / checking network
        warm_executor_cache(&action).await?;
        container.start_execution(...).await
    }
    other => other,
}

Prevention

When it happens

Trigger: executor_action.spawn(&current_dir, approvals_service, &env) taking >30s to return — slow executor binary download/startup, hung credential prompt, filesystem stall, or executor waiting for interactive input.

Common situations: Cold start with no cached executor (large npx/pip fetch), offline or proxied environments blocking downloads, antivirus/permission scans delaying process start, misconfigured executor command that waits on stdin.

Understand the failure class

Related errors


AI-assisted analysis of BloopAI/vibe-kanban@4deb7eca8f (2026-08-29). Data as JSON: /api/errors/4a67d2f4eb0f997a. Report an issue: GitHub.