googleapis/mcp-toolbox · error

failed to read object %q in bucket %q: %w

Error message

failed to read object %q in bucket %q: %w

What it means

io.ReadAll failed while streaming the object body after it was opened successfully. The wrapped error is usually a network interruption mid-read, a context cancellation/deadline, or an integrity/checksum mismatch reported by the GCS client.

Source

Thrown at internal/sources/cloudstorage/cloudstorage.go:266

func (s *Source) ReadObject(ctx context.Context, bucket, object string, offset, length int64) (map[string]any, error) {
	if err := s.validateBucket(bucket); err != nil {
		return nil, err
	}
	reader, err := s.client.Bucket(bucket).Object(object).NewRangeReader(ctx, offset, length)
	if err != nil {
		return nil, fmt.Errorf("failed to open object %q in bucket %q: %w", object, bucket, err)
	}
	defer reader.Close()

	if remain := reader.Remain(); remain > defaultMaxReadBytes {
		return nil, fmt.Errorf("object %q: %d bytes exceeds %d byte limit: %w",
			object, remain, defaultMaxReadBytes,
			cloudstoragecommon.ErrReadSizeLimitExceeded)
	}

	data, err := io.ReadAll(reader)
	if err != nil {
		return nil, fmt.Errorf("failed to read object %q in bucket %q: %w", object, bucket, err)
	}

	if !utf8.Valid(data) {
		return nil, fmt.Errorf("object %q in bucket %q: %w", object, bucket,
			cloudstoragecommon.ErrBinaryContent)
	}

	return map[string]any{
		"content":     string(data),
		"contentType": reader.Attrs.ContentType,
		"size":        len(data),
	}, nil
}

// ListBuckets lists buckets in a project. When project is empty, the source's
// configured project is used. maxResults == 0 returns up to the GCS per-page
// default (1000). A non-empty pageToken resumes listing. The returned map
// contains "buckets" ([]*storage.BucketAttrs) and "nextPageToken" (empty when

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Retry the read with exponential backoff; transient network drops are usually recoverable.
  2. Extend the context timeout / remove premature cancellation so the full read can complete.
  3. Reduce the amount read per call (smaller offset/length ranges) to shorten each transfer.
  4. If errors persist with checksum/integrity messages, verify the object isn't being mutated mid-read and check proxy/LB idle timeouts.

Example fix

// before
ctx := context.Background()
res, err := source.ReadObject(ctx, "bkt", "obj", 0, -1) // cancelled mid-read
// after
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer cancel()
res, err := source.ReadObject(ctx, "bkt", "obj", 0, -1) // retry once on transient err
Defensive patterns

Strategy: retry

Validate before calling

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer cancel()

Try / catch

if errors.Is(ctx.Err(), context.DeadlineExceeded) || errors.Is(ctx.Err(), context.Canceled) {
    // extend timeout / reschedule
}
// otherwise retry the read with exponential backoff

Prevention

When it happens

Trigger: ReadObject on an object where the connection drops mid-transfer, the context is cancelled (client timeout, server shutdown), or the GCS client detects a corrupted response (CRC mismatch).

Common situations: Long reads over flaky networks or mobile/VPN links; server-side request timeouts shorter than download duration on huge objects; context deadlines from the MCP client expiring during transfer.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/99ce2559bf372b03. Report an issue: GitHub.