fix(backends/vastai): route /instances/ to /api/v1/ (v0 deprecated, returns HTTP 410)#3969
fix(backends/vastai): route /instances/ to /api/v1/ (v0 deprecated, returns HTTP 410)#3969evolv3ai wants to merge 1 commit into
Conversation
Vast.ai deprecated /api/v0/instances/, returning HTTP 410 "deprecated_endpoint". dstack interprets that as "Invalid credentials" during auth_test() and refuses to register the backend. Only the /instances/ path family is deprecated; /bundles/ and /asks/ remain on v0 (v1 not yet published for them). The v1 instances response preserves the existing schema (success flag, instances list); it adds pagination fields the existing code ignores. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5dcaac677b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if path.lstrip("/").startswith("instances/"): | ||
| base = base.replace("/api/v0", "/api/v1") |
There was a problem hiding this comment.
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 👍 / 👎.
| if path.lstrip("/").startswith("instances/"): | ||
| base = base.replace("/api/v0", "/api/v1") |
There was a problem hiding this comment.
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 👍 / 👎.
Problem
VastAIAPIClient._url()insrc/dstack/_internal/core/backends/vastai/api_client.pyhardcodeshttps://console.vast.ai/api/v0for all Vast API calls. Vast.ai has deprecated only the/api/v0/instances/path family — the endpoint now responds with HTTP 410deprecated_endpoint.Reproduction (any current dstack release, including
masterand PyPI 0.20.24):This breaks
vastaibackend registration:auth_test()callsget_instances(), the 410 is raised as an HTTPError, dstack reports it back to the operator as "Invalid credentials". The API key is fine — the URL is dead./bundles/and/asks/still work on v0 (v1 is not yet published for them), so offer queries and instance creation are unaffected — only the/instances/family needs the v1 prefix.Fix
Route paths under
/instances/(coversget_instances,destroy_instance,request_logs) to/api/v1/. Leave/bundles/and/asks/on v0. The v1 instances response preserves the existing schema (successflag,instanceslist); it adds pagination fields the existing code ignores.Verification
Applied to a self-hosted dstack 0.20.23 broker. Before: backend registration fails with "Invalid credentials". After patch + restart:
POST /api/project/<p>/backends/create_yaml→ 200vastaidstack offer --backend vastai --gpu A6000returns 7+ live offersdstack applyof a task config successfully provisions a Vast.ai instance through the patched code path (instance transitions provisioning → running cleanly)Notes
_url()helper changes. No new dependencies, no behavioral change forbundles/askscallers.masterand on every tagged release I checked (0.20.20 through 0.20.24)./api/v1/bundles/and/api/v1/asks/later, the same conditional shape will accept additional path prefixes cleanly.Co-Authored-By: Claude Opus 4.7 noreply@anthropic.com