zed-industries/zed · error

copilot was not started because of an error

Error message

copilot was not started because of an error: {error}

What it means

The third branch of as_running(): startup was attempted and failed, and the failure was stored in CopilotServer::Error(error). This bail re-raises that stored cause with a wrapper message, so the {error} text after the colon is the real diagnosis — typically a binary-install failure, unsupported platform/arch (see errors 178/179), an npm error, or the language server process dying at spawn. The state is sticky: every subsequent call re-surfaces the same stored error until Copilot is restarted or reinstalled.

Solutions

  1. Read the {error} suffix first — it is the actual failure; fix that cause (network, disk, registry) rather than this wrapper
  2. Use the built-in reinstall path (Copilot::reinstall) to re-download the language server after fixing the environment
  3. Clear the copilot directory (paths::copilot_dir) if a previous partial install is suspected, then retry
  4. Verify the platform/arch is linux/macOS/windows on x64/arm64; otherwise Copilot cannot run (see errors 178/179)

Example fix

# before: error stored, every call re-fails
# 'copilot was not started because of an error: ... npm ENOTFOUND registry.npmjs.org'

# after: fix network/DNS, then trigger reinstall
# editor: run 'copilot: reinstall' (Copilot::reinstall) and retry sign-in
Defensive patterns

Strategy: try-catch

Validate before calling

use copilot::Status;

if let Status::Error(msg) = copilot.read(cx).status() {
    // stale stored failure — trigger reinstall before invoking APIs
    copilot.update(cx, |c, cx| { c.reinstall(cx); });
    return Task::ready(Err(anyhow!("copilot startup failed earlier: {msg}")));
}

Type guard

fn copilot_in_error(copilot: &Entity<Copilot>, cx: &App) -> Option<String> {
    match copilot.read(cx).status() {
        Status::Error(msg) => Some(msg),
        _ => None,
    }
}

Try / catch

match result {
    Err(err) if err.to_string().contains("was not started because of an error") => {
        // the suffix after the colon is the real cause; it is sticky until reinstall/restart
        diagnose_stored_error(&err);
        copilot.update(cx, |c, cx| { c.reinstall(cx); }); // recovery path
    }
    other => other,
}

Prevention

When it happens

Trigger: Any Copilot API call after start_copilot failed — e.g. npm install of copilot-language-server errored (registry unreachable, disk full), the platform/arch is unsupported, or the spawned process exited immediately; the stored error then bubbles through as_running() on all later calls.

Common situations: Offline or proxied network blocking npm download of the language server package; corporate npm registry mirror missing @github/copilot-language-server-*; out-of-disk in the copilot directory; OS/arch combination with no prebuilt binary (freebsd, 32-bit); stale half-written install from an interrupted update.

Related errors


AI-assisted analysis of zed-industries/zed@f4178619ac (2026-08-20). Data as JSON: /api/errors/0abeee519f52c02a. Report an issue: GitHub.

Appendix: source

Thrown at crates/copilot/src/copilot.rs:79

    Running(RunningCopilotServer),
}

impl CopilotServer {
    fn as_authenticated(&mut self) -> Result<&mut RunningCopilotServer> {
        let server = self.as_running()?;
        anyhow::ensure!(
            matches!(server.sign_in_status, SignInStatus::Authorized),
            "must sign in before using copilot"
        );
        Ok(server)
    }

    fn as_running(&mut self) -> Result<&mut RunningCopilotServer> {
        match self {
            CopilotServer::Starting { .. } => anyhow::bail!("copilot is still starting"),
            CopilotServer::Disabled => anyhow::bail!("copilot is disabled"),
            CopilotServer::Error(error) => {
                anyhow::bail!("copilot was not started because of an error: {error}")
            }
            CopilotServer::Running(server) => Ok(server),
        }
    }
}

struct RunningCopilotServer {
    lsp: Arc<LanguageServer>,
    sign_in_status: SignInStatus,
    registered_buffers: HashMap<EntityId, RegisteredBuffer>,
}

#[derive(Clone, Debug)]
enum SignInStatus {
    Authorized,
    Unauthorized,
    SigningIn {
        prompt: Option<request::PromptUserDeviceFlow>,

View on GitHub (pinned to f4178619ac)