github/github-mcp-server · error

failed to download log content for job %d: %w

Error message

failed to download log content for job %d: %w

What it means

Returned by getJobLogData (pkg/github/actions.go:153) when downloadLogContent fails after the log URL was already obtained. It wraps one of three inner failures: transport error fetching the signed blob URL ('failed to download logs: %w'), a non-200 status ('failed to download logs: HTTP %d'), or a body-streaming error ('failed to process log content: %w'). The httpResp is converted to a github.Response so error-reporting middleware still sees status context.

Source

Thrown at pkg/github/actions.go:153

	}
	defer func() { _ = resp.Body.Close() }()

	result := map[string]any{
		"job_id": jobID,
	}
	if jobName != "" {
		result["job_name"] = jobName
	}

	if returnContent {
		// Download and return the actual log content
		content, originalLength, httpResp, err := downloadLogContent(ctx, url.String(), tailLines, contentWindowSize) //nolint:bodyclose // Response body is closed in downloadLogContent, but we need to return httpResp
		if err != nil {
			var ghResp *github.Response
			if httpResp != nil {
				ghResp = &github.Response{Response: httpResp}
			}
			return nil, ghResp, fmt.Errorf("failed to download log content for job %d: %w", jobID, err)
		}
		result["logs_content"] = content
		result["message"] = "Job logs content retrieved successfully"
		result["original_length"] = originalLength
	} else {
		// Return just the URL
		result["logs_url"] = url.String()
		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")

View on GitHub (pinned to 0ea1f775a7)

Solutions

  1. Unwrap the inner error to identify which of the three failures occurred, then apply its specific fix
  2. Retry immediately - a fresh call re-obtains a fresh signed URL, fixing expiry-related 403s
  3. Verify network egress to objects.githubusercontent.com
  4. Reduce tail_lines to shrink the download window if transfers keep breaking

Example fix

// before
if err != nil {
    return err // opaque nested error
}

// after - branch on the wrapped cause
var ghErr *ghErrors.GitHubAPIError
if errors.As(err, &ghErr) && ghErr.Response != nil {
    switch ghErr.Response.StatusCode {
    case 403:
        return retryWithFreshURL() // signed URL expired
    case 404:
        return fmt.Errorf("log blob gone (expired retention)")
    }
}
Defensive patterns

Strategy: retry

Validate before calling

// Pre-check egress and freshness before requesting content
if returnContent && !hostReachable("objects.githubusercontent.com") {
    return errors.New("blob storage unreachable; use return_content=false for URL only")
}

Try / catch

if err != nil {
    if strings.Contains(err.Error(), "HTTP 403") {
        return retryWithFreshURL() // signed URL expired
    }
    if strings.Contains(err.Error(), "HTTP 404") {
        return err // purged blob: not retryable
    }
    return retryOnce() // transport/streaming: transient
}

Prevention

When it happens

Trigger: Calling action_job_logs with return_content=true where the follow-up GET of the signed URL (from the 302 redirect of GetWorkflowJobLogs) fails: network break, expired signed URL returning 403, blob deleted returning 404, or the ring-buffer reader hitting a mid-body error.

Common situations: Delay between getting the signed URL and fetching it (URLs are short-lived); egress blocking objects.githubusercontent.com; large logs cut off by proxies; token has API access but the environment cannot reach GitHub's blob storage.

Related errors


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