Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/dstack/_internal/core/backends/vastai/api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,13 @@ def auth_test(self) -> bool:
return False

def _url(self, path):
return f"{self.api_url}/{path.lstrip('/')}?api_key={self.api_key}"
base = self.api_url
# Vast.ai deprecated /api/v0/instances/ (HTTP 410). /api/v1/instances/
# returns a schema-compatible response (success flag + instances list).
# /bundles/ and /asks/ remain on v0; v1 is not yet published for them.
if path.lstrip("/").startswith("instances/"):
base = base.replace("/api/v0", "/api/v1")
Comment on lines +142 to +143

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep non-list instance calls on v0

This prefix check sends every /instances/... URL to v1, including destroy_instance() and request_logs(). The current Vast docs only move the list endpoint to GET /api/v1/instances/; they still document destruction as DELETE /api/v0/instances/{id}/ and logs as PUT /api/v0/instances/request_logs/{id}. In VastAI runs, terminate_instance() relies on destroy_instance() and ignores a false return, so routing deletes to an unpublished v1 endpoint can leave paid instances running while also breaking log retrieval.

Useful? React with 👍 / 👎.

Comment on lines +142 to +143

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Page through v1 instance results

Routing get_instances() to v1 changes the response from the old unpaginated list to Vast's paginated endpoint: the docs state limit defaults to 25, has max 25, and provide next_token for additional pages. Since the existing client caches only data["instances"], accounts with more than 25 matching instances can have a dstack instance omitted, causing get_instance() to return None and update_provisioning_data() to stop discovering SSH/status data for that run.

Useful? React with 👍 / 👎.

return f"{base}/{path.lstrip('/')}?api_key={self.api_key}"

def _invalidate_cache(self):
with self.lock:
Expand Down