Skip to content

Commit 151fca9

Browse files
authored
fix(server): return already_exists for duplicate sandbox names (#695)
Check for existing sandbox name before persisting, matching the provider-creation pattern. The CLI now surfaces a clear hint instead of a raw UNIQUE constraint error. Closes #691
1 parent 2538bea commit 151fca9

File tree

3 files changed

+24
-6
lines changed

3 files changed

+24
-6
lines changed

crates/openshell-cli/src/run.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2045,7 +2045,16 @@ pub async fn sandbox_create(
20452045
name: name.unwrap_or_default().to_string(),
20462046
};
20472047

2048-
let response = client.create_sandbox(request).await.into_diagnostic()?;
2048+
let response = match client.create_sandbox(request).await {
2049+
Ok(resp) => resp,
2050+
Err(status) if status.code() == Code::AlreadyExists => {
2051+
return Err(miette::miette!(
2052+
"{}\n\nhint: delete it first with: openshell sandbox delete <name>\n or use a different name",
2053+
status.message()
2054+
));
2055+
}
2056+
Err(status) => return Err(status).into_diagnostic(),
2057+
};
20492058
let sandbox = response
20502059
.into_inner()
20512060
.sandbox

crates/openshell-server/src/grpc.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,20 @@ impl OpenShell for OpenShellService {
244244
..Default::default()
245245
};
246246

247+
// Reject duplicate names early, before touching the index or store.
248+
// This mirrors the provider-creation pattern (see `create_provider`).
249+
let existing = self
250+
.state
251+
.store
252+
.get_message_by_name::<Sandbox>(&name)
253+
.await
254+
.map_err(|e| Status::internal(format!("fetch sandbox failed: {e}")))?;
255+
if existing.is_some() {
256+
return Err(Status::already_exists(format!(
257+
"sandbox '{name}' already exists"
258+
)));
259+
}
260+
247261
// Persist to the store FIRST so the sandbox watcher always finds
248262
// the record with `spec` populated. If we created the k8s
249263
// resource first, the watcher could race us and write a fallback

e2e/python/test_inference_routing.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,6 @@ def _upsert_managed_inference(
9595
except grpc.RpcError as create_exc:
9696
if create_exc.code() == grpc.StatusCode.ALREADY_EXISTS:
9797
continue
98-
if (
99-
create_exc.code() == grpc.StatusCode.INTERNAL
100-
and "UNIQUE constraint failed" in (create_exc.details() or "")
101-
):
102-
continue
10398
raise
10499
else:
105100
raise RuntimeError("failed to upsert managed e2e provider after retries")

0 commit comments

Comments
 (0)