heygen-com/hyperframes · error
Failed to publish project
Error message
Failed to publish project
What it means
publishProjectArchiveDirect: the direct POST to /v1/hyperframes/projects/publish returned a Response, but either !response.ok (HTTP 4xx/5xx) OR parsePublishedProjectResponse returned null (payload missing required fields: project_id, title, url, file_count, or claim_token for anonymous publishes). readErrorMessage extracts the server's JSON message field or response body, falling back to the literal 'Failed to publish project'. This is a server-level error response, distinct from the transport-level [255].
Source
Thrown at packages/cli/src/utils/publishProject.ts:576
new File([archiveArrayBuffer(archive)], `${title}.zip`, { type: PUBLISH_CONTENT_TYPE }),
);
const headers: Record<string, string> = { ...authHeaders };
const response = await fetchForPublish(
`${apiBaseUrl}/v1/hyperframes/projects/publish`,
() => ({
method: "POST",
body,
headers,
signal: AbortSignal.timeout(uploadTimeoutMs(archive.buffer.byteLength)),
}),
"Failed to publish project",
);
const payload = await readJson(response);
const publishedProject = parsePublishedProjectResponse(payload);
if (!response.ok || !publishedProject) {
throw new Error(await readErrorMessage(response, "Failed to publish project"));
}
return publishedProject;
}
async function uploadArchiveToPresignedUrl(
stagedUpload: StagedUploadResponse,
archive: PublishArchiveResult,
): Promise<void> {
const presignedUrlTtlMs = stagedUpload.expiresInSeconds * 1000 - PUBLISH_METADATA_TIMEOUT_MS;
const s3Response = await fetchForPublish(
stagedUpload.uploadUrl,
() => ({
method: "PUT",
body: new Blob([archiveArrayBuffer(archive)], { type: stagedUpload.contentType }),
headers: stagedUpload.uploadHeaders,
signal: AbortSignal.timeout(
Math.min(uploadTimeoutMs(archive.buffer.byteLength), presignedUrlTtlMs),View on GitHub (pinned to c2996c8626)
Solutions
- Read the full error message — it includes the server's response body or JSON message field.
- For 401/403, refresh credentials (re-authenticate) and retry.
- For 400, address the specific validation error (title characters, archive size, etc.).
- For 5xx, retry after a short wait — transient server errors are common.
- For malformed-response (no specific HTTP error), capture the raw response body and report it as a server bug.
Defensive patterns
Strategy: try-catch
Try / catch
try {
return await publishProjectArchive(projectDir, opts);
} catch (err) {
if (err instanceof Error && /Failed to publish project/.test(err.message)) {
// err.message carries the server's response text — log and surface to user
console.error('Publish rejected by server:', err.message);
// for 401/403, prompt re-auth; for 5xx, retry after backoff
} else throw err;
} Prevention
- Re-authenticate before publishing if credentials may have expired.
- Validate the project title (avoid disallowed characters) before publish.
- For anonymous publishes, ensure the server returns a claim_token — if not, report it as a server bug.
When it happens
Trigger: The API rejected the publish: authentication failed (401), rate limited (429), validation error (400 — e.g. bad title), server error (500), or the response JSON was present but malformed/incomplete (missing project_id/url/etc.). Also when an anonymous publish response omitted claim_token (which parsePublishedProjectResponse treats as invalid).
Common situations: Expired or invalid auth credentials; publishing a project that exceeds size/feature limits; a title with disallowed characters; the API is temporarily returning 500s; a partial service outage where the metadata endpoint is up but the publish backend is degraded; an anonymous publish where the server bug omitted claim_token.
Related errors
- Failed to prepare project upload
- Failed to upload project archive
- figma ref ${ref.fileKey} has no nodeId
- [handler] chunk URI at index ${i} is empty
- PLAN_V2_INTEGRITY_UNRECOVERABLE
AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12).
Data as JSON: /api/errors/fc0dfa079db13dad.
Report an issue: GitHub.