heygen-com/hyperframes · error
Failed to prepare project upload
Error message
Failed to prepare project upload
What it means
publishProjectArchiveStaged: the initial POST to /v1/hyperframes/projects/publish/upload returned a non-OK HTTP status that is NOT 404 or 405 (those signal 'staged uploads unsupported' and cause a fallback to direct publish, returning null — not an error). So this fires on 400/401/403/500/etc. from the upload-preparation endpoint, OR when the response parsed but parseStagedUploadResponse returned null (missing upload_url or upload_key). readErrorMessage extracts the server message. This is the metadata stage of staged publishing, before any bytes are uploaded.
Source
Thrown at packages/cli/src/utils/publishProject.ts:640
}),
headers: {
...authHeaders,
"content-type": "application/json",
},
signal: AbortSignal.timeout(PUBLISH_METADATA_TIMEOUT_MS),
}),
"Failed to prepare project upload",
PUBLISH_TRANSPORT_ATTEMPTS,
);
if (uploadResponse.status === 404 || uploadResponse.status === 405) {
return null;
}
const uploadPayload = await readJson(uploadResponse);
const stagedUpload = parseStagedUploadResponse(uploadPayload, archive.buffer.byteLength);
if (!uploadResponse.ok || !stagedUpload) {
throw new Error(await readErrorMessage(uploadResponse, "Failed to prepare project upload"));
}
await uploadArchiveToPresignedUrl(stagedUpload, archive);
const completeResponse = await fetchForPublish(
`${apiBaseUrl}/v1/hyperframes/projects/publish/complete`,
() => ({
method: "POST",
body: JSON.stringify({
upload_key: stagedUpload.uploadKey,
file_name: fileName,
title,
...(isPublic ? { is_public: true } : {}),
...(projectId ? { project_id: projectId } : {}),
}),
headers: {
...authHeaders,
"content-type": "application/json",View on GitHub (pinned to c2996c8626)
Solutions
- Read the embedded server message — it names the specific rejection reason.
- For 401/403, re-authenticate and retry.
- For 400, ensure content_type is application/zip and content_length matches the archive byte length.
- For 5xx, retry after a short wait.
- If staged uploads are genuinely unsupported, the server should return 404/405 (which fall back to direct publish); a 500 here is a server bug worth reporting.
Defensive patterns
Strategy: try-catch
Try / catch
try {
return await publishProjectArchive(projectDir, opts);
} catch (err) {
if (err instanceof Error && /Failed to prepare project upload/.test(err.message)) {
// err.message includes server text; 401 -> re-auth, 5xx -> retry, else report
console.error('Staged upload prep failed:', err.message);
} else throw err;
} Prevention
- Ensure credentials are valid before publish (re-auth on 401).
- Keep content_type as application/zip and content_length matching the archive size.
- If the server's staged-upload endpoint is flaky, a retry usually clears transient 5xx responses.
When it happens
Trigger: Auth failure (401) on the staged-upload endpoint; rate limiting (429); the server rejects the content_type or content_length declared in the JSON body; a server bug returns 200 but omits upload_url/upload_key from the payload (parseStagedUploadResponse -> null); the staged-upload feature is partially deployed (returns 500 instead of 404).
Common situations: Expired credentials; a content_type the server does not accept; a content_length mismatch (archive changed between build and the upload-prep request); server-side incident affecting only the staged-upload endpoint; an anonymous publish hitting a staged-upload endpoint that requires auth.
Related errors
- Failed to publish project
- Failed to upload project archive
- OpenRouter request failed with HTTP ${res.status}
- Registry item "${item.name}" declares invalid minCliVersion
- Speech was generated but metadata could not be read. Check t
AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12).
Data as JSON: /api/errors/eb258105714d1d73.
Report an issue: GitHub.