Summary
brev create cannot place an instance in a specific region. The control-plane API does accept location / subLocation on the plain (non-launchable) create endpoint, and store.CreateWorkspacesOptions already declares both fields — but nothing outside the launchable path ever populates them. The result is that every plain brev create silently inherits whatever default location the instance-type catalog happens to carry for that type.
For n2d-standard-2 that default is currently asia-south1, so a user in the US who runs brev create mybox --type n2d-standard-2 deterministically gets an instance in Mumbai with no flag available to change it and nothing in the output indicating a region was chosen.
Impact
I hit this provisioning a small CPU node intended to sit next to existing us-west2 infrastructure. Three delete/recreate cycles all landed in asia-south1 — it reads like capacity flakiness, but it's deterministic. Cross-region latency to the rest of the fleet was ~238 ms.
Notably, an existing instance of the same type (n2d-standard-2) in the same org is in us-west2, so the placement is achievable — the CLI just can't ask for it.
Root cause
The fields exist in the request struct, with omitempty:
// pkg/store/workspace.go:101-102
InstanceType string `json:"instanceType"`
Location string `json:"location,omitempty"`
SubLocation string `json:"subLocation,omitempty"`
DiskStorage string `json:"diskStorage"`
The only assignments to them in the repo are in the launchable path:
// pkg/cmd/gpucreate/gpucreate.go:1365-1376
func applyLaunchableWorkspaceRequest(cwOptions *store.CreateWorkspacesOptions, wsReq store.LaunchableWorkspaceRequest) {
if wsReq.Location != "" {
cwOptions.Location = wsReq.Location
}
if wsReq.SubLocation != "" {
cwOptions.SubLocation = wsReq.SubLocation
}
createWorkspace() (the non-launchable path) never sets either, so omitempty drops them and the server falls back to the catalog default.
Two related places where location data is available but discarded:
gpusearch.InstanceType parses location, sub_location, and available_locations, but ProcessInstances() maps into GPUInstanceInfo, which has no location field — so the data is dropped, and brev search has no LOCATION column to reveal where a type would land.
GetAllInstanceTypesWithCloudCreds passes uniqueInstanceType = true, deduplicating region variants down to a single row; GetCloudCredID() then takes the first match.
Reproduction
brev create mybox --type n2d-standard-2
# -> lands in asia-south1 regardless of caller location; no flag to influence it
Confirm the catalog default that drives it:
curl -s -H "Authorization: Bearer $TOKEN" \
"https://brevapi.us-west-2-prod.control-plane.brev.dev/api/instances/alltypesavailable/$ORG_ID" \
| jq '.[] | .[]? | select(.type=="n2d-standard-2")
| {location, sub_location, available_locations}'
Returns location: "asia-south1", with available_locations containing 40 regions including us-west2.
The server already supports this (verified)
Adding the field to the same plain-create endpoint works. I ran this and it returned region: us-west2:
curl -X POST "https://brevapi.us-west-2-prod.control-plane.brev.dev/api/organizations/$ORG_ID/workspaces" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{
"name": "mybox",
"workspaceGroupId": "GCP",
"workspaceClassId": "2x8",
"workspaceTemplateId": "<template-id>",
"instanceType": "n2d-standard-2",
"diskStorage": "120Gi",
"workspaceVersion": "v1",
"vmBuild": {"forceJupyterInstall": true},
"location": "us-west2",
"subLocation": "us-west2-a"
}'
So this is purely a CLI gap, not a backend limitation. It's also consistent with the existing test comment in gpucreate_test.go, which notes that the original bug was fields the server expected (firewallRules, subLocation) being missing from the request body.
Requested change
- Add
--location (and optionally --sub-location) flags to brev create, wired into CreateWorkspacesOptions.Location / .SubLocation.
- Validate the value against the type's
available_locations and fail with the list on mismatch.
- Surface location in
brev search output (a LOCATION column) and in brev create --dry-run, so the default is visible before creating.
- Consider whether
uniqueInstanceType = true should dedupe across regions, given it can hide region variants entirely.
Even just (3) alone would have saved a lot of time here — the current behavior is invisible until after the instance exists.
Environment
brev v0.6.329 (also checked v0.6.334 release notes; no region-related changes)
- Linux, GCP provider, instance type
n2d-standard-2
Summary
brev createcannot place an instance in a specific region. The control-plane API does acceptlocation/subLocationon the plain (non-launchable) create endpoint, andstore.CreateWorkspacesOptionsalready declares both fields — but nothing outside the launchable path ever populates them. The result is that every plainbrev createsilently inherits whatever defaultlocationthe instance-type catalog happens to carry for that type.For
n2d-standard-2that default is currentlyasia-south1, so a user in the US who runsbrev create mybox --type n2d-standard-2deterministically gets an instance in Mumbai with no flag available to change it and nothing in the output indicating a region was chosen.Impact
I hit this provisioning a small CPU node intended to sit next to existing
us-west2infrastructure. Three delete/recreate cycles all landed inasia-south1— it reads like capacity flakiness, but it's deterministic. Cross-region latency to the rest of the fleet was ~238 ms.Notably, an existing instance of the same type (
n2d-standard-2) in the same org is inus-west2, so the placement is achievable — the CLI just can't ask for it.Root cause
The fields exist in the request struct, with
omitempty:The only assignments to them in the repo are in the launchable path:
createWorkspace()(the non-launchable path) never sets either, soomitemptydrops them and the server falls back to the catalog default.Two related places where location data is available but discarded:
gpusearch.InstanceTypeparseslocation,sub_location, andavailable_locations, butProcessInstances()maps intoGPUInstanceInfo, which has no location field — so the data is dropped, andbrev searchhas no LOCATION column to reveal where a type would land.GetAllInstanceTypesWithCloudCredspassesuniqueInstanceType = true, deduplicating region variants down to a single row;GetCloudCredID()then takes the first match.Reproduction
brev create mybox --type n2d-standard-2 # -> lands in asia-south1 regardless of caller location; no flag to influence itConfirm the catalog default that drives it:
Returns
location: "asia-south1", withavailable_locationscontaining 40 regions includingus-west2.The server already supports this (verified)
Adding the field to the same plain-create endpoint works. I ran this and it returned
region: us-west2:So this is purely a CLI gap, not a backend limitation. It's also consistent with the existing test comment in
gpucreate_test.go, which notes that the original bug was fields the server expected (firewallRules,subLocation) being missing from the request body.Requested change
--location(and optionally--sub-location) flags tobrev create, wired intoCreateWorkspacesOptions.Location/.SubLocation.available_locationsand fail with the list on mismatch.brev searchoutput (a LOCATION column) and inbrev create --dry-run, so the default is visible before creating.uniqueInstanceType = trueshould dedupe across regions, given it can hide region variants entirely.Even just (3) alone would have saved a lot of time here — the current behavior is invisible until after the instance exists.
Environment
brevv0.6.329 (also checked v0.6.334 release notes; no region-related changes)n2d-standard-2