edit_prediction: Skip cloud Zeta requests when not signed in (#57615) (cherry-pick to preview) (#58045)
Some checks failed
run_tests / orchestrate (push) Has been cancelled
run_tests / check_style (push) Has been cancelled
run_tests / clippy_windows (push) Has been cancelled
run_tests / clippy_linux (push) Has been cancelled
run_tests / clippy_mac (push) Has been cancelled
run_tests / clippy_mac_x86_64 (push) Has been cancelled
run_tests / run_tests_windows (push) Has been cancelled
run_tests / run_tests_linux (push) Has been cancelled
run_tests / run_tests_mac (push) Has been cancelled
run_tests / miri_scheduler (push) Has been cancelled
run_tests / doctests (push) Has been cancelled
run_tests / check_workspace_binaries (push) Has been cancelled
run_tests / build_visual_tests_binary (push) Has been cancelled
run_tests / check_wasm (push) Has been cancelled
run_tests / check_dependencies (push) Has been cancelled
run_tests / check_docs (push) Has been cancelled
run_tests / check_licenses (push) Has been cancelled
run_tests / check_scripts (push) Has been cancelled
run_tests / check_postgres_and_protobuf_migrations (push) Has been cancelled
run_tests / extension_tests (push) Has been cancelled
run_tests / tests_pass (push) Has been cancelled

Cherry-pick of #57615 to preview

----
Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX

checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Closes #57962

## What

When a user is not signed in to their Zed account, the edit prediction
system was still attempting a cloud API request on every keystroke. The
request would fail deep in the credential check
(`CloudApiClient::build_request`) with a `ClientApiError::NotSignedIn`
error, which propagated back up and was logged at `ERROR` level via
`.log_err()` at line 2389 of `edit_prediction.rs`.

## Why

The sign-in check was happening too late — only discovered after async
tasks were already spawned and the full request pipeline entered. This
fix gates the request at the top of `request_prediction_internal`,
returning `Task::ready(Ok(None))` immediately before any inputs are
built or tasks spawned.

The guard mirrors the existing `is_cloud` provider check already used
elsewhere in the same file, and only applies to the `Zeta` model on the
cloud provider path. Local providers (Ollama, `OpenAiCompatibleApi`) and
other models (Mercury, Fim) are unaffected.

Note: I haven't added a test for this — testing the early-return would
require mocking auth state, which I wasn't sure was worth the complexity
for a one-liner guard. Happy to add one if preferred.

Release Notes:

- Fixed noisy `not signed in` error log on every keystroke when not
signed in to Zed

---------

Co-authored-by: Oleksiy Syvokon <oleksiy@zed.dev>
Co-authored-by: MrSubidubi <finn@zed.dev>
Co-authored-by: David3u <3udavid@gmail.com>

Co-authored-by: Seth Wood <sethlwood@me.com>
Co-authored-by: Oleksiy Syvokon <oleksiy@zed.dev>
Co-authored-by: MrSubidubi <finn@zed.dev>
Co-authored-by: David3u <3udavid@gmail.com>
This commit is contained in:
zed-zippy[bot] 2026-05-29 07:31:24 +00:00 committed by GitHub
parent ddf89f77ef
commit fcf0321414
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 23 additions and 10 deletions

View file

@ -2530,6 +2530,15 @@ impl EditPredictionStore {
allow_jump: bool,
cx: &mut Context<Self>,
) -> Task<Result<Option<EditPredictionResult>>> {
let is_cloud_zeta = matches!(self.edit_prediction_model, EditPredictionModel::Zeta)
&& !matches!(
all_language_settings(None, cx).edit_predictions.provider,
EditPredictionProvider::Ollama | EditPredictionProvider::OpenAiCompatibleApi
);
if is_cloud_zeta && !self.client.cloud_client().has_credentials() {
return Task::ready(Ok(None));
}
self.get_or_init_project(&project, cx);
let project_state = self.projects.get(&project.entity_id()).unwrap();
let stored_events = project_state.events(cx);

View file

@ -3107,11 +3107,18 @@ async fn test_unauthenticated_without_custom_url_blocks_prediction_impl(cx: &mut
let project = Project::test(fs.clone(), [path!("/project").as_ref()], cx).await;
let http_client = FakeHttpClient::create(|_req| async move {
Ok(gpui::http_client::Response::builder()
.status(401)
.body("Unauthorized".into())
.unwrap())
let request_count = Arc::new(std::sync::atomic::AtomicUsize::default());
let http_client = FakeHttpClient::create({
let request_count = request_count.clone();
move |_req| {
request_count.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
async move {
Ok(gpui::http_client::Response::builder()
.status(401)
.body("Unauthorized".into())
.unwrap())
}
}
});
let client =
@ -3144,11 +3151,8 @@ async fn test_unauthenticated_without_custom_url_blocks_prediction_impl(cx: &mut
ep_store.request_prediction(&project, &buffer, cursor, Default::default(), cx)
});
let result = completion_task.await;
assert!(
result.is_err(),
"Without authentication and without custom URL, prediction should fail"
);
assert!(completion_task.await.unwrap().is_none());
assert_eq!(request_count.load(std::sync::atomic::Ordering::SeqCst), 0);
}
#[gpui::test]