ThreeMammals/Ocelot · error · Exception

UploadFileToGitHubRelease: StatusCode is

Error message

UploadFileToGitHubRelease: StatusCode is 

What it means

UploadFileToGitHubRelease uploads a release asset to the GitHub uploads URL and requires HTTP 201 Created. Non-201 statuses (401, 403, 404, 422) throw this error. The log line before the throw includes the release ID, file name, and full upload URL.

Solutions

  1. Check the logged uploadUrl and StatusCode; 404 usually means the release ID or URL template is wrong.
  2. 422: an asset with that name already exists — delete it or make the upload idempotent.
  3. 401/403: fix the token scope/secret used by SetupGitHubClient.
  4. Verify the upload URL is built as {upload_url without {name,label}} + '?name={fileName}'.
  5. Confirm the file exists and is under GitHub's 2GB asset limit.

Example fix

// before
uploadUrl = parts[0] + "=" + fileName;
// after
uploadUrl = parts[0] + "?name=" + Uri.EscapeDataString(fileName);
Defensive patterns

Strategy: retry

Validate before calling

var assetExists = GetReleaseAssets(releaseId).Any(a => a.name == fileName);
if (assetExists) { Warning($"Asset {fileName} already uploaded; skipping."); return; }

Try / catch

try { UploadFileToGitHubRelease(release, fileName, filePath); }
catch (Exception ex) when (ex.Message.Contains("StatusCode is ")) { Error($"Asset upload failed: {ex.Message}"); throw; }

Prevention

When it happens

Trigger: Asset upload rejected: bad/insufficient token (401/403), wrong upload URL after parsing the release's upload_url (404), asset name already exists (422), or file too large (>2GB limit).

Common situations: Re-running a release where the asset was already uploaded; malformed uploadUrl templating (the '?name=' substitution); uploading packages artifacts that exceed GitHub limits; token scope regression in CI secrets.

Related errors


AI-assisted analysis of ThreeMammals/Ocelot@d1f22d9304 (2026-09-12). Data as JSON: /api/errors/91adf205dd1fdc32. Report an issue: GitHub.

Appendix: source

Thrown at build.cake:1048

	var data = _File_.ReadAllBytes(file.FullPath);
	var content = new System.Net.Http.ByteArrayContent(data);
	content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");

	using (var client = new System.Net.Http.HttpClient())
	{	
		SetupGitHubClient(client);
		int releaseId = release.id;
		var fileName = file.GetFilename();
		string uploadUrl = release.upload_url.ToString();
		// Information($"UploadFileToGitHubRelease: uploadUrl is {uploadUrl}");
		string[] parts = uploadUrl.Replace("{", "").Split(',');
		uploadUrl = parts[0] + "=" + fileName; // $"https://uploads.github.com/repos/ThreeMammals/Ocelot/releases/{releaseId}/assets?name={fileName}"
		Information($"UploadFileToGitHubRelease: uploadUrl is {uploadUrl}");
		var result = client.PostAsync(uploadUrl, content).Result;
		if (result.StatusCode != System.Net.HttpStatusCode.Created) 
		{
			Information($"UploadFileToGitHubRelease: StatusCode is {result.StatusCode}. Release ID is {releaseId}. Failed to upload file '{fileName}' to URL: {uploadUrl}");
			throw new Exception("UploadFileToGitHubRelease: StatusCode is " + result.StatusCode);
		}
	}
}

private void CompleteGitHubRelease(dynamic release)
{
	int releaseId = release.id;
	string url = release.url.ToString();
	string body = ReleaseNotesAsJson();
	bool isPreRelease = !IsMainBranch();
	var json = $"{{ \"tag_name\": \"{versioning.NuGetVersion}\", \"target_commitish\": \"{versioning.BranchName}\", \"name\": \"{versioning.NuGetVersion}\", \"body\": \"{body}\", \"draft\": false, \"prerelease\": {isPreRelease.ToString().ToLower()} }}";
	var request = new System.Net.Http.HttpRequestMessage(new System.Net.Http.HttpMethod("Patch"), url); // $"https://api.github.com/repos/ThreeMammals/Ocelot/releases/{releaseId}");
	request.Content = new System.Net.Http.StringContent(json, System.Text.Encoding.UTF8, "application/json");

	using (var client = new System.Net.Http.HttpClient())
	{	
		SetupGitHubClient(client);
		var result = client.SendAsync(request).Result;

View on GitHub (pinned to d1f22d9304)