{"record":{"id":"d9ccd8689e4577f7","repo":"mastra-ai/mastra","slug":"no-upload-url-returned-d9ccd8","errorCode":null,"errorMessage":"No upload URL returned","messagePattern":"No upload URL returned","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"packages/cli/src/commands/studio/platform-api.ts","lineNumber":167,"sourceCode":"        'x-mastra-version': meta?.mastraVersion,\n      },\n    },\n    body: {\n      envVars: meta?.envVars,\n      ...(meta?.disablePlatformObservability !== undefined\n        ? { disablePlatformObservability: meta.disablePlatformObservability }\n        : {}),\n    },\n  });\n\n  if (error) {\n    throwApiError('Deploy failed', response.status, error.detail);\n  }\n\n  const { id, status, uploadUrl } = data.deploy;\n\n  if (!uploadUrl) {\n    throw new Error('No upload URL returned');\n  }\n\n  const cancel = (c: ReturnType<typeof createApiClient>) =>\n    bestEffortCancel({\n      postCancel: c2 => c2.POST('/v1/studio/deploys/{id}/cancel', { params: { path: { id } } }),\n      client: c,\n      deployId: id,\n    });\n\n  // Step 2: Upload artifact to the signed URL\n  try {\n    if (uploadUrl.startsWith('file://')) {\n      const { writeFile } = await import('node:fs/promises');\n      const { fileURLToPath } = await import('node:url');\n      await writeFile(fileURLToPath(uploadUrl), Buffer.from(zipBuffer));\n    } else {\n      const uploadResp = await fetch(uploadUrl, {\n        method: 'PUT',","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/cli/src/commands/studio/platform-api.ts#L149-L185","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\npnpm dlx mastra@old studio deploy --yes\n// Error: No upload URL returned\n// after\npnpm dlx mastra@latest studio deploy --yes","handlingStrategy":"retry","validationCode":"const { data } = await client.POST('/v1/studio/deploys', { body });\nconst deploy = data?.deploy as { id: string; uploadUrl?: string } | undefined;\nif (!deploy?.uploadUrl) {\n  throw new Error(`API returned no uploadUrl for deploy ${deploy?.id ?? '?'}`);\n}","typeGuard":"function hasUploadUrl(d: { uploadUrl?: unknown }): d is { uploadUrl: string } {\n  return typeof d.uploadUrl === 'string' && d.uploadUrl.length > 0;\n}","tryCatchPattern":"try {\n  await uploadDeploy(zipBuffer);\n} catch (e) {\n  if (e instanceof Error && e.message === 'No upload URL returned') {\n    console.error('Server did not provide an upload URL; update CLI and retry once.');\n    process.exitCode = 3;\n  } else throw e;\n}","preventionTips":["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"],"tags":["api","network","cli"],"backgroundTag":"missing-upload-url","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}