zed-industries/zed · error · Error
Could not find UNIT_DATA in the file
Error message
Could not find UNIT_DATA in the file
What it means
Thrown by CopilotServer::as_running() when the Copilot extension is in its Error state, meaning the background language-server start task already failed and the failure message was stored in CopilotServer::Error(Arc<str>). The wrapper 'copilot was not started because of an error: {error}' prepends context and embeds the original start failure (e.g. npm download failure, missing binary, spawn error). Callers hit this from as_authenticated()/as_running() at buffer registration (copilot.rs:167, 202) and completion requests (copilot.rs:1019, 1191). The state is entered at copilot.rs:724-725 when start_language_server returns Err, or forced via the ZED_FORCE_COPILOT_ERROR env var for testing.
Source
Thrown at script/cargo-timing-info.js:35
}
const xdgDataHome = process.env.XDG_DATA_HOME || path.join(os.homedir(), ".local", "share");
return path.join(xdgDataHome, "zed");
} else if (platform === "win32") {
// Windows: LocalAppData/Zed
const localAppData = process.env.LOCALAPPDATA || path.join(os.homedir(), "AppData", "Local");
return path.join(localAppData, "Zed");
} else {
// Fallback to XDG config dir
const xdgConfigHome = process.env.XDG_CONFIG_HOME || path.join(os.homedir(), ".config");
return path.join(xdgConfigHome, "zed");
}
}
function extractUnitData(htmlContent) {
// Find the UNIT_DATA array in the file
const unitDataMatch = htmlContent.match(/const\s+UNIT_DATA\s*=\s*(\[[\s\S]*?\]);/);
if (!unitDataMatch) {
throw new Error("Could not find UNIT_DATA in the file");
}
try {
return JSON.parse(unitDataMatch[1]);
} catch (e) {
throw new Error(`Failed to parse UNIT_DATA as JSON: ${e.message}`);
}
}
function formatTime(seconds) {
if (seconds < 60) {
return `${seconds.toFixed(2)}s`;
}
const minutes = Math.floor(seconds / 60);
const remainingSeconds = seconds % 60;
return `${minutes}m ${remainingSeconds.toFixed(2)}s`;
}
View on GitHub (pinned to bc538def45)
Solutions
- Read the embedded {error} text — it is the verbatim start failure and names the real cause (network, binary, platform).
- Trigger a reinstall via the copilot: Reinstall action (reinstall() at copilot.rs:841), which clears the copilot dir and re-runs the download.
- If the embedded error mentions network, fix connectivity/proxy (check HTTP_PROXY/HTTPS_PROXY) and retry the reinstall.
- If the embedded error is 'unsupported Copilot language server platform/architecture', the OS/arch is not linux/macOS/windows on aarch64/x86_64 — Copilot cannot run there.
- Delete paths::copilot_dir() (remove_matching clears it) to force a clean install if the directory is corrupted.
- Verify ZED_FORCE_COPILOT_ERROR is not set in the environment.
Example fix
// before: calling completions blindly on a possibly-failed server
let response = copilot.completions(&cursor_position, &buffer, cx).await?;
// after: check the public status first and surface a retry path
match copilot.status() {
Status::Error(error) => {
// show `error` to the user and offer the Reinstall action
return Err(anyhow!("copilot failed to start: {error}"));
}
Status::Starting { .. } => { /* wait for the start task, then retry */ }
_ => { let response = copilot.completions(&cursor_position, &buffer, cx).await?; }
} Defensive patterns
Strategy: try-catch
Validate before calling
// Rust equivalent of pre-call validation: check the public status surface
// before invoking any completion/registration API.
use copilot::Status;
fn copilot_ready(status: &Status) -> bool {
matches!(status, Status::Authorized)
} Type guard
fn usable_copilot_status(status: &Status) -> bool {
matches!(
status,
Status::Authorized | Status::Unauthorized | Status::SigningIn { .. } | Status::SignedOut { .. }
)
} Try / catch
// Result-based (Rust): inspect the message only to classify, never to parse
if let Err(err) = result {
let msg = format!("{err:#}");
if msg.starts_with("copilot was not started") {
// server-state error: offer Reinstall, do not retry blindly
}
} Prevention
- Render copilot.status() in the UI (status bar item already does this) so users see Error before invoking actions.
- Route all failures through one handler that maps Status::Error(e) to a Reinstall action instead of retrying the failed call.
- In tests, use the ZED_FORCE_COPILOT_ERROR env var to exercise this path deterministically.
- Never call completion APIs from background tasks without first checking status() on the foreground thread.
When it happens
Trigger: Calling any API that routes through as_running()/as_authenticated() — register_buffer, completion, status queries — after the server start task failed (network error while fetching @github/copilot-language-server from npm, unsupported platform/architecture bail, language server process exited during initialize). Also reproducible deterministically by setting ZED_FORCE_COPILOT_ERROR=1 before launching.
Common situations: Offline machine or proxy blocking registry.npmjs.org so npm_install_latest_packages fails; corrupted copilot directory under paths::copilot_dir() causing spawn failure; running an unsupported platform build (e.g. FreeBSD) so copilot_lsp_native_binary_path bails; leftover Error state after a transient network outage that was never retried because only reinstall() clears it.
Related errors
- HTTP error! status: ${response.status}
- GraphQL error: ${JSON.stringify(data.errors)}
- Failed to parse UNIT_DATA as JSON: ${e.message}
- Unexpected response structure: ${JSON.stringify(data)}
- Missing env var `ZED_SERVER_URL`
AI-assisted analysis of zed-industries/zed@bc538def45 (2026-08-16).
Data as JSON: /api/errors/944854912f4e263c.
Report an issue: GitHub.