zed-industries/zed · warning
copilot is still starting
Error message
copilot is still starting
What it means
The Copilot integration models its language-server lifecycle as the CopilotServer enum: Starting, Disabled, Error, Running. Almost every operation funnels through as_running()/as_authenticated(), and while the npm package is still being installed/downloaded and the language server process has not finished launching, the state is Starting and any request (completions, sign-in, register_buffer) bails with 'copilot is still starting'. This is a transient state error: the same call typically succeeds once startup completes.
Solutions
- Wait for startup to finish and retry the operation — the state advances automatically once the language server process is up
- Trigger the download early (open the Copilot UI/sign-in flow once) so the package is cached before you need completions
- Check network/npm-registry access if Starting persists for minutes (the underlying install may be silently slow or failing and will surface as the Error state)
- In code that drives Copilot programmatically, gate requests on status()/language_server() being ready instead of calling immediately
Example fix
// before
let status = copilot.update(cx, |c, cx| c.sign_in(cx))?; // may hit Starting
// after
if copilot.read(cx).language_server().is_none() {
// wait / show 'starting' UI instead of invoking
}
let task = copilot.update(cx, |c, cx| c.sign_in(cx)); Defensive patterns
Strategy: retry
Validate before calling
// gate on readiness before invoking Copilot APIs
if copilot.read(cx).language_server().is_none() {
// still Starting (or Disabled/Error) — defer the call
return Task::ready(Err(anyhow!("copilot not ready yet")));
}
copilot.update(cx, |c, cx| c.sign_in(cx)) Type guard
fn copilot_ready(copilot: &Entity<Copilot>, cx: &App) -> bool {
copilot.read(cx).language_server().is_some() // Some only when Running
} Try / catch
// state error, not a value error: catch, check, wait for the state change, retry
match result {
Err(err) if err.to_string().contains("copilot is still starting") => {
// re-run after the startup task notifies; don't spawn tight-loop retries
retry_after_state_change(copilot).await
}
other => other,
} Prevention
- Observe the Copilot entity and drive UI off status() instead of calling APIs blind
- Warm the download early in a session so the Starting window is short
- Treat persistent Starting as an install problem in progress — check network, not the API call
When it happens
Trigger: Calling any Copilot API (e.g. sign_in, register_buffer, completion requests) through methods that use as_running() during the window after the agent is created but before start_copilot's install+spawn task moves the state to Running — first use in a session, slow network on first download of the npm package.
Common situations: Cold start: first Copilot request right after editor launch before the @github/copilot-language-server package downloads; slow npm registry or offline machine stretching the Starting phase; tests invoking completion immediately after initializing the Copilot agent.
Related errors
- copilot was not started because of an error
- copilot is disabled
- GitHub Copilot native language server binary was not…
- unsupported Copilot language server architecture
- Copilot did not provide an output limit for this model
AI-assisted analysis of zed-industries/zed@f4178619ac (2026-08-20).
Data as JSON: /api/errors/f9412c68a39fcde4.
Report an issue: GitHub.
Appendix: source
Thrown at crates/copilot/src/copilot.rs:76
Disabled,
Starting { task: Shared<Task<()>> },
Error(Arc<str>),
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,View on GitHub (pinned to f4178619ac)