{"record":{"id":"0738391d79b85e48","repo":"zed-industries/zed","slug":"http-error-status-response-status","errorCode":null,"errorMessage":"HTTP error! status: ${response.status}","messagePattern":"HTTP error! status: (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"script/get-release-notes-since","lineNumber":90,"sourceCode":"  let allReleases = [];\n  let hasNextPage = true;\n  let cursor = null;\n\n  while (hasNextPage) {\n    const response = await fetch(\"https://api.github.com/graphql\", {\n      method: \"POST\",\n      headers: {\n        Authorization: `Bearer ${GITHUB_ACCESS_TOKEN}`,\n        \"Content-Type\": \"application/json\",\n      },\n      body: JSON.stringify({\n        query,\n        variables: { owner: \"zed-industries\", repo: \"zed\", cursor },\n      }),\n    });\n\n    if (!response.ok) {\n      throw new Error(`HTTP error! status: ${response.status}`);\n    }\n\n    const data = await response.json();\n\n    if (data.errors) {\n      throw new Error(`GraphQL error: ${JSON.stringify(data.errors)}`);\n    }\n\n    if (!data.data || !data.data.repository || !data.data.repository.releases) {\n      throw new Error(`Unexpected response structure: ${JSON.stringify(data)}`);\n    }\n\n    const releases = data.data.repository.releases.nodes;\n    allReleases = allReleases.concat(releases);\n\n    hasNextPage = data.data.repository.releases.pageInfo.hasNextPage;\n    cursor = data.data.repository.releases.pageInfo.endCursor;\n","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/zed-industries/zed/blob/bc538def4545534201bbfcac4e95ac34ea6501b6/script/get-release-notes-since#L72-L108","documentation":"Returned as an immediately-ready Err task by Copilot::sign_in (copilot.rs:814) when self.server is not CopilotServer::Running. The in-code comment states the intent: while the server is Starting (npm download in progress) the caller should wait for the start task, and in a stuck/Error state the UI should show it to the user. So this is a lifecycle-guard error, not a failure of sign-in itself: Disabled, Starting, and Error states all fall into the else branch.","triggerScenarios":"Invoking sign_in before the background start task finished (CopilotServer::Starting, e.g. first-ever launch still downloading the npm package), after the server entered CopilotServer::Error, or while edit predictions are disabled so the server is CopilotServer::Disabled.","commonSituations":"User clicks 'Sign in to GitHub Copilot' seconds after first install while the language server is still downloading; a UI element calling sign_in on window focus without checking status; Copilot disabled in settings (edit_predictions provider off) but a stale sign-in button still visible; retrying sign-in after a start failure without reinstalling.","solutions":["Wait for startup to finish: poll/await the Status returned by copilot.status() until it is no longer Status::Starting (the start task stored in Starting { task } completes and flips the state).","If status is Error(e), address the underlying start error (see 'copilot was not started because of an error') or run copilot: Reinstall, then sign in.","If status is Disabled, enable edit predictions with Copilot in settings (\"edit_predictions\": { \"mode\": \"subword\", \"copilot\": { ... } } / select Copilot as provider) so the server actually starts.","Only call sign_in when status() is one of SignedOut/Unauthorized/SigningIn/Authorized."],"exampleFix":"// before\nlet result = copilot.sign_in(cx).await; // fires too early during download\n\n// after: gate on the public status enum\nmatch copilot.status() {\n    Status::Starting { task } => { task.await; copilot.sign_in(cx).await }\n    Status::Error(e) => Err(anyhow!(\"copilot not started: {e}\")),\n    Status::Disabled => Err(anyhow!(\"copilot is disabled in settings\")),\n    _ => copilot.sign_in(cx).await,\n}","handlingStrategy":"validation","validationCode":"// Only sign in against a live server; wait out the Starting phase first.\nmatch copilot.status() {\n    Status::Starting { task } => task.await, // download finishes, state flips\n    _ => {}\n}\nif !matches!(copilot.status(), Status::Disabled | Status::Error(_)) {\n    copilot.sign_in(cx).await?;\n}","typeGuard":"fn can_sign_in_now(status: &Status) -> bool {\n    !matches!(status, Status::Starting { .. } | Status::Error(_) | Status::Disabled)\n}","tryCatchPattern":"if let Err(err) = copilot.sign_in(cx).await {\n    if format!(\"{err}\").contains(\"hasn't started yet\") {\n        // lifecycle race: re-check status() and re-dispatch, do not show as fatal\n    } else {\n        return Err(err);\n    }\n}","preventionTips":["Gate every sign_in call site on status() not being Starting/Error/Disabled.","Disable the sign-in button while Status::Starting is active.","Remember update_sign_in_status already handles retries: re-invoking sign_in after NotSignedIn is always valid.","In UI flows, await the Starting task handle from status() before prompting the user."],"tags":["copilot","zed","lifecycle","sign-in","race-condition"],"backgroundTag":null,"analyzedSha":"bc538def4545534201bbfcac4e95ac34ea6501b6","analyzedAt":"2026-08-16T07:30:46.435Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}