mastra-ai/mastra · critical · Error
No upload URL returned
Error message
No upload URL returned
What it means
uploadDeploy first POSTs to /v1/studio/deploys to create a deploy record and expects the response's deploy object to include a presigned uploadUrl. If the API responds successfully (2xx) but omits uploadUrl, the client cannot upload the zip and throws instead of failing obscurely later.
Source
Thrown at packages/cli/src/commands/studio/platform-api.ts:167
'x-mastra-version': meta?.mastraVersion,
},
},
body: {
envVars: meta?.envVars,
...(meta?.disablePlatformObservability !== undefined
? { disablePlatformObservability: meta.disablePlatformObservability }
: {}),
},
});
if (error) {
throwApiError('Deploy failed', response.status, error.detail);
}
const { id, status, uploadUrl } = data.deploy;
if (!uploadUrl) {
throw new Error('No upload URL returned');
}
const cancel = (c: ReturnType<typeof createApiClient>) =>
bestEffortCancel({
postCancel: c2 => c2.POST('/v1/studio/deploys/{id}/cancel', { params: { path: { id } } }),
client: c,
deployId: id,
});
// Step 2: Upload artifact to the signed URL
try {
if (uploadUrl.startsWith('file://')) {
const { writeFile } = await import('node:fs/promises');
const { fileURLToPath } = await import('node:url');
await writeFile(fileURLToPath(uploadUrl), Buffer.from(zipBuffer));
} else {
const uploadResp = await fetch(uploadUrl, {
method: 'PUT',View on GitHub (pinned to 75dd419e61)
Solutions
- Update @mastra/cli (and core packages) to the latest version so the API contract matches
- Retry the deploy — transient server issues can omit the upload URL
- Check Mastra status/changelog for known API incidents
- If persisting, report the issue with the deploy id and response captured via debug logging
Example fix
// before pnpm dlx mastra@old studio deploy --yes // Error: No upload URL returned // after pnpm dlx mastra@latest studio deploy --yes
Defensive patterns
Strategy: retry
Validate before calling
const { data } = await client.POST('/v1/studio/deploys', { body });
const deploy = data?.deploy as { id: string; uploadUrl?: string } | undefined;
if (!deploy?.uploadUrl) {
throw new Error(`API returned no uploadUrl for deploy ${deploy?.id ?? '?'}`);
} Type guard
function hasUploadUrl(d: { uploadUrl?: unknown }): d is { uploadUrl: string } {
return typeof d.uploadUrl === 'string' && d.uploadUrl.length > 0;
} Try / catch
try {
await uploadDeploy(zipBuffer);
} catch (e) {
if (e instanceof Error && e.message === 'No upload URL returned') {
console.error('Server did not provide an upload URL; update CLI and retry once.');
process.exitCode = 3;
} else throw e;
} Prevention
- Keep the CLI updated to match the current Studio API contract
- Retry once on this error before escalating (transient server issues)
- Capture API responses (debug logging) when reporting the issue
- Watch Mastra status/changelog for deploy-API incidents
When it happens
Trigger: The Studio API returns a deploy payload without uploadUrl — typically a server-side/contract change, an unexpected API version mismatch between CLI and server, or the deploy record being created in a state that skips URL generation.
Common situations: Running an outdated CLI against a newer API (or vice versa); server incident where deploys are created but upload signing fails silently; proxy/gateway stripping or rewriting response bodies.
Related errors
- Failed to fetch logs: ${error.detail}
- Failed to fetch templates: ${response.statusText}
- Telegram ${method} failed: ${detail}
- Perplexity Search request failed with status ${response.stat
- ${err instanceof Error ? err.message : String(err)}\nYou can
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/d9ccd8689e4577f7.
Report an issue: GitHub.