github/github-mcp-server · error

failed to download logs: HTTP %d

Error message

failed to download logs: HTTP %d

What it means

Returned by downloadLogContent (pkg/github/actions.go:179) when the GET of the signed log URL completes but returns a status other than 200 - the body of that response is discarded and only the code is reported. Because GetWorkflowJobLogs redirects to a short-lived signed blob URL, the two dominant causes are an expired signature (403) and a deleted/purged blob (404).

Source

Thrown at pkg/github/actions.go:179

		result["message"] = "Job logs are available for download"
		result["note"] = "The logs_url provides a download link for the individual job logs in plain text format. Use return_content=true to get the actual log content."
	}

	return result, resp, nil
}

func downloadLogContent(ctx context.Context, logURL string, tailLines int, maxLines int) (string, int, *http.Response, error) {
	prof := profiler.New(nil, profiler.IsProfilingEnabled())
	finish := prof.Start(ctx, "log_buffer_processing")

	httpResp, err := http.Get(logURL) //nolint:gosec
	if err != nil {
		return "", 0, httpResp, fmt.Errorf("failed to download logs: %w", err)
	}
	defer func() { _ = httpResp.Body.Close() }()

	if httpResp.StatusCode != http.StatusOK {
		return "", 0, httpResp, fmt.Errorf("failed to download logs: HTTP %d", httpResp.StatusCode)
	}

	bufferSize := min(tailLines, maxLines)

	processedInput, totalLines, httpResp, err := buffer.ProcessResponseAsRingBufferToEnd(httpResp, bufferSize)
	if err != nil {
		return "", 0, httpResp, fmt.Errorf("failed to process log content: %w", err)
	}

	lines := strings.Split(processedInput, "\n")
	if len(lines) > tailLines {
		lines = lines[len(lines)-tailLines:]
	}
	finalResult := strings.Join(lines, "\n")

	_ = finish(len(lines), int64(len(finalResult)))

	return finalResult, totalLines, httpResp, nil

View on GitHub (pinned to 0ea1f775a7)

Solutions

  1. Do not cache or reuse the logs_url - fetch it fresh via GetWorkflowJobLogs on every attempt
  2. On 404, accept the logs are purged (retention expired) and re-run the workflow if logs are needed
  3. On 403 with an error page body, check proxy rules for objects.githubusercontent.com
  4. Retry once with a fresh URL - expiry clears immediately

Example fix

// before
url, _, _ := client.Actions.GetWorkflowJobLogs(ctx, owner, repo, jobID, 1)
time.Sleep(10 * time.Minute) // URL goes stale
http.Get(url.String()) // -> HTTP 403

// after - always fetch a fresh URL right before downloading
url, _, err := client.Actions.GetWorkflowJobLogs(ctx, owner, repo, jobID, 1)
if err != nil {
    return err
}
resp, err := http.Get(url.String()) // use immediately
if err == nil && resp.StatusCode != http.StatusOK {
    url, _, _ = client.Actions.GetWorkflowJobLogs(ctx, owner, repo, jobID, 1) // refresh once
    resp, err = http.Get(url.String())
}
Defensive patterns

Strategy: retry

Validate before calling

// Do not pre-validate a stale URL - validate your flow instead:
// always fetch the URL and download it in the same turn
url, _, err := client.Actions.GetWorkflowJobLogs(ctx, owner, repo, jobID, 1)
if err != nil {
    return err
}
resp, err := http.Get(url.String()) // immediately after fetching
_ = resp

Try / catch

if resp.StatusCode != http.StatusOK {
    if resp.StatusCode == 403 {
        url, _, _ = client.Actions.GetWorkflowJobLogs(ctx, owner, repo, jobID, 1) // fresh signature
        resp, err = http.Get(url.String())
    }
    if resp.StatusCode == 404 {
        return errors.New("log blob purged (retention expired)") // not retryable
    }
}

Prevention

When it happens

Trigger: Delay between obtaining the signed URL and downloading it so the signature expires (403); log blob already garbage-collected after retention expiry (404); rare 5xx from blob storage; any interception layer answering with 4xx before GitHub storage is reached.

Common situations: Retried or cached log URLs reused minutes later; expired retention purging blobs while the API still lists the job; proxies returning 407/403 for storage domains.

Related errors


AI-assisted analysis of github/github-mcp-server@0ea1f775a7 (2026-08-15). Data as JSON: /api/errors/034a30f904bc1821. Report an issue: GitHub.