{"record":{"id":"19860302ede42a1b","repo":"mastra-ai/mastra","slug":"failed-to-complete-upload-err-as-detail-st","errorCode":null,"errorMessage":"Failed to complete upload: ${(err as { detail?: string }).detail || completeResp.statusText}","messagePattern":"Failed to complete upload: (.+?)\\)\\.detail \\|\\| completeResp\\.statusText\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/deploy/index.ts","lineNumber":398,"sourceCode":"    throw new Error(`Failed to upload artifact: ${uploadResp.statusText}`);\n  }\n\n  // Signal upload complete — uses net-new env-scoped endpoint so the\n  // unified-runtime CLI never touches /v1/studio/*.\n  const completeResp = await fetch(\n    `${apiUrl}/v1/projects/${projectId}/environments/${environmentId}/deploys/${deploy.id}/upload-complete`,\n    {\n      method: 'POST',\n      headers: {\n        Authorization: `Bearer ${token}`,\n        'x-organization-id': orgId,\n      },\n    },\n  );\n\n  if (!completeResp.ok) {\n    const err = await completeResp.json().catch(() => ({}));\n    throw new Error(`Failed to complete upload: ${(err as { detail?: string }).detail || completeResp.statusText}`);\n  }\n\n  return deploy;\n}\n\ninterface UnifiedDeployStatus {\n  id: string;\n  status: string;\n  instanceUrl: string | null;\n  error: string | null;\n}\n\n/**\n * Poll the net-new env-scoped status endpoint until the deploy reaches a\n * terminal state. Kept inside the deploy command so the unified runtime\n * never reaches into ../studio/ for transport.\n */\nasync function streamEnvironmentDeployLogs(","sourceCodeStart":380,"sourceCodeEnd":416,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/cli/src/commands/deploy/index.ts#L380-L416","documentation":"The final step of uploadToEnvironment signals the platform that the artifact upload finished (upload-complete endpoint). A non-ok response throws with the server's `detail` when available, else statusText. The artifact bytes may already be stored, but the deploy was not finalized, so the platform may keep the deploy in an incomplete state.","triggerScenarios":"The POST to /v1/projects/{projectId}/environments/{environmentId}/deploys/{deploy.id}/upload-complete returns non-2xx — e.g., server-side verification of the uploaded artifact failed, auth expired between steps, or the deploy record was cancelled/unknown.","commonSituations":"Token expiry mid-deploy in long CI runs; upload-complete racing server-side artifact verification; concurrent deploy superseding this one; platform-side validation rejecting an unexpected artifact layout.","solutions":["Read the `detail` in the message for the server's exact reason","Re-run the deploy end-to-end (a fresh create/upload cycle) rather than retrying only upload-complete","Check token validity/auth duration for long CI jobs and refresh or extend it","Confirm no other deploy pipeline is concurrently targeting the same environment"],"exampleFix":"// before\n// 40-min CI job, token expires before upload-complete -> 401\n// after\n// refresh token before deploy step (or use a token with sufficient expiry), re-run deploy","handlingStrategy":"try-catch","validationCode":"// Ensure the token won't expire mid-deploy for long CI jobs\nconst jobDurationMs = 40 * 60 * 1000;\nconst tokenTtlMs = getTokenTtl(token); // decode exp from token\nif (tokenTtlMs < jobDurationMs) throw new Error('Token expires before deploy can finish; refresh it');","typeGuard":"function isCompleteUploadFailure(err: unknown): err is Error {\n  return err instanceof Error && err.message.startsWith('Failed to complete upload:');\n}","tryCatchPattern":"try {\n  const deploy = await uploadToEnvironment(args);\n} catch (err) {\n  if (isCompleteUploadFailure(err)) {\n    console.error('Deploy not finalized:', err.message);\n    // re-run the full deploy (create + upload + complete), not just upload-complete\n  } else throw err;\n}","preventionTips":["Use tokens with TTL exceeding the whole CI job duration","Re-run the entire deploy flow after a finalize failure — don't call upload-complete standalone","Avoid concurrent deploy pipelines on the same environment","Log the `detail` field for platform-side support when it persists"],"tags":["http","api","deploy","finalization"],"backgroundTag":"deploy-finalize-failed","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}