googleapis/mcp-toolbox · error

object %q in bucket %q: %w

Error message

object %q in bucket %q: %w

What it means

The object's bytes were read successfully but are not valid UTF-8, so the source rejects them by wrapping cloudstoragecommon.ErrBinaryContent. The tool returns text content only, and binary data cannot be represented in the string response.

Source

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

	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
// there are no more results).
func (s *Source) ListBuckets(ctx context.Context, project, prefix string, maxResults int, pageToken string) (map[string]any, error) {
	if project == "" {
		project = s.Project

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Only call ReadObject on text objects; check the object's contentType (via ListObjects/metadata) is text/*, application/json, etc. first.
  2. For binary objects, download via gsutil/the GCS client instead of this text-oriented tool.
  3. If the file is meant to be text but fails UTF-8 validation, re-upload it after converting encoding (e.g. iconv to UTF-8).
  4. Handle ErrBinaryContent (errors.Is) in the caller and surface a friendly 'binary content not supported' message to the user.

Example fix

// before
res, err := source.ReadObject(ctx, "bkt", "images/logo.png", 0, -1) // binary
// after
if isTextContentType("image/png") == false { return errors.New("use a binary download path for this object") }
res, err := source.ReadObject(ctx, "bkt", "notes/readme.txt", 0, -1)
Defensive patterns

Strategy: validation

Validate before calling

func isTextContentType(ct string) bool {
    ct = strings.ToLower(ct)
    return strings.HasPrefix(ct, "text/") || ct == "application/json" || ct == "application/yaml"
}
// check object contentType before ReadObject

Type guard

func isBinaryContentErr(err error) bool {
    return errors.Is(err, cloudstoragecommon.ErrBinaryContent)
}

Try / catch

if errors.Is(err, cloudstoragecommon.ErrBinaryContent) {
    return nil, fmt.Errorf("object is binary; use a download tool instead")
}

Prevention

When it happens

Trigger: ReadObject on binary objects: images (PNG/JPEG), archives (zip/tar.gz), PDFs, Parquet/Avro, or any file with invalid UTF-8 sequences anywhere in the read range.

Common situations: LLM user asking to 'read' a .png or .zip from a bucket; listing bucket contents and reading every object without filtering by content-type; offset/length windows landing inside multibyte or binary regions of mixed-encoding files.

Related errors


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