anomalyco/sst · error

failed to initialize assets upload: HTTP %d %s

Error message

failed to initialize assets upload: HTTP %d %s

What it means

uploadAssetManifest POSTs the asset manifest to Cloudflare's assets-upload-session endpoint and throws this error when the HTTP status is not 200. The response body is embedded in the message, so it carries Cloudflare's own error explanation (auth failure, bad script name, invalid manifest, rate limit, etc.).

Source

Thrown at pkg/server/resource/cloudflare-worker-assets.go:196

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBody))
	if err != nil {
		return nil, err
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+apiToken)

	client := &http.Client{Timeout: 30 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	// print out response body as a string
	if resp.StatusCode != http.StatusOK {
		responseBody, _ := io.ReadAll(resp.Body)
		return nil, fmt.Errorf("failed to initialize assets upload: HTTP %d %s", resp.StatusCode, string(responseBody))
	}

	var result struct {
		Result InitializeAssetsResponse `json:"result"`
	}

	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return nil, err
	}

	if result.Result.Jwt == "" {
		return nil, fmt.Errorf("failed to initialize assets upload: no JWT received")
	}

	return &result.Result, nil
}

func (r *WorkerAssets) uploadAssets(manifest AssetManifest, directory, accountId, apiToken string, hashes []string, jwt string) (string, error) {

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Read the embedded HTTP status and response body in the error to identify Cloudflare's exact complaint.
  2. Verify apiToken has 'Workers Scripts:Edit' permission and is valid for the target account.
  3. Confirm the Worker script (scriptName) already exists in the given account before uploading assets.
  4. Check accountId matches the account that owns the script.
  5. If status is 429 or 5xx, retry after a short backoff.

Example fix

// before
curl -X POST "https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/workers/scripts/my-worker/assets-upload-session" \
  -H "Authorization: Bearer $WRANGLER_TOKEN" -d '{"manifest":{}}'
// after: use a token scoped to the right account with Workers Scripts edit permission
wrangler whoami  # confirm account + token scopes before deploying
Defensive patterns

Strategy: try-catch

Validate before calling

// validate token + script before calling upload
async function preflight(accountId: string, scriptName: string, token: string) {
  const res = await fetch(
    `https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/scripts/${scriptName}`,
    { headers: { Authorization: `Bearer ${token}` } }
  );
  if (!res.ok) throw new Error(`preflight failed: HTTP ${res.status} ${await res.text()}`);
}

Try / catch

try {
  await deployAssets();
} catch (e) {
  const m = /HTTP (\d+) /.match(String(e));
  if (m && [429, 500, 502, 503].includes(+m[1])) {
    await retryWithBackoff(deployAssets);
  } else {
    throw new Error(`Cloudflare rejected asset session: ${e.message} - check token scopes, accountId, and scriptName`);
  }
}

Prevention

When it happens

Trigger: Any non-200 response from POST /accounts/{accountId}/workers/scripts/{scriptName}/assets-upload-session: 401/403 (bad or insufficient apiToken), 404 (scriptName does not exist), 400 (malformed manifest JSON), 429 (rate limited), 5xx (Cloudflare outage).

Common situations: API token missing Workers Scripts edit permission or expired; deploying assets before the Worker script was created; wrong accountId in config; manifest containing paths Cloudflare rejects; hitting Cloudflare during an incident or rate limit.

Related errors


AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30). Data as JSON: /api/errors/5aab6edc1012452b. Report an issue: GitHub.