dgraph-io/dgraph · error

Failed to read s3 object

Error message

Failed to read s3 object

What it means

s3Handler.Read wraps minio.GetObject client-side failures with 'Failed to read s3 object'. This fires when obtaining the object reader itself fails (client/config error); errors during streaming the body produce the sibling 'Failed to read the s3 object' message instead.

Solutions

  1. Check the wrapped cause for minio's error type (BucketDoesNotExist, ObjectDoesNotExist, auth, connection).
  2. Verify credentials (access/secret, session token) and endpoint/TLS settings.
  3. Confirm the object exists: mc ls / head-object on bucket+objectPath (check objectPrefix).
  4. Test network reachability to the endpoint (curl/DNS) and correct region/virtual-host settings.
  5. Re-run the operation once connectivity/auth is fixed — reads are safe to retry.

Example fix

// before
reader, err := h.mc.GetObject(ctx, h.bucketName, objectPath, minio.GetObjectOptions{})
if err != nil {
    return buf.Bytes(), errors.Wrap(err, "Failed to read s3 object")
}
// after
reader, err := h.mc.GetObject(ctx, h.bucketName, objectPath, minio.GetObjectOptions{})
if err != nil {
    resp := minio.ToErrorResponse(err)
    return buf.Bytes(), errors.Wrapf(err, "Failed to read s3 object (code=%s)", resp.Code)
}
Defensive patterns

Strategy: retry

Validate before calling

ok, err := h.mc.BucketExists(ctx, h.bucketName)
if err != nil || !ok {
    return fmt.Errorf("bucket %s unreachable or missing: %v", h.bucketName, err)
}
if _, err := h.mc.StatObject(ctx, h.bucketName, h.getObjectPath(path), minio.StatObjectOptions{}); err != nil {
    return fmt.Errorf("object %s missing: %v", path, err)
}

Try / catch

data, err := handler.Read(p)
if err != nil {
    if strings.Contains(err.Error(), "Failed to read s3 object") {
        return retryWithBackoff(3, func() error { _, e := handler.Read(p); return e })
    }
    return err
}

Prevention

When it happens

Trigger: minio.GetObject returns an error before any read: invalid bucket/object path, bad credentials/endpoint configuration, network failure to the S3 endpoint, or wrong-region bucket — while calling s3Handler.Read.

Common situations: Wrong minio endpoint or TLS config; deleted or non-existent backup object; IAM/key revoked; DNS/network outage to the S3 endpoint; object name mismatch due to prefix misconfiguration.

Related errors


AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01). Data as JSON: /api/errors/c6a17e17a5b1f535. Report an issue: GitHub.

Appendix: source

Thrown at worker/backup_handler.go:311

	}
	errResponse := minio.ToErrorResponse(err)
	if errResponse.Code != "NoSuchKey" {
		glog.Errorf("Failed to verify object existence: %v", err)
	}
	return false
}

func (h *s3Handler) JoinPath(path string) string {
	return filepath.Join(h.bucketName, h.objectPrefix, cleanRelPath(path))
}

func (h *s3Handler) Read(path string) ([]byte, error) {
	objectPath := h.getObjectPath(path)
	var buf bytes.Buffer

	reader, err := h.mc.GetObject(context.Background(), h.bucketName, objectPath, minio.GetObjectOptions{})
	if err != nil {
		return buf.Bytes(), errors.Wrap(err, "Failed to read s3 object")
	}
	defer reader.Close()

	if _, err := buf.ReadFrom(reader); err != nil {
		return buf.Bytes(), errors.Wrap(err, "Failed to read the s3 object")
	}
	return buf.Bytes(), nil
}

func (h *s3Handler) Stream(path string) (io.ReadCloser, error) {
	objectPath := h.getObjectPath(path)
	reader, err := h.mc.GetObject(context.Background(), h.bucketName, objectPath, minio.GetObjectOptions{})
	if err != nil {
		return nil, err
	}
	return reader, nil
}

View on GitHub (pinned to 759e242be6)