Tencent/WeKnora · error

failed to initialize MinIO client: %w

Error message

failed to initialize MinIO client: %w

What it means

newMinioClient wraps an error returned by minio.New (minio-go/v7 SDK client construction) as "failed to initialize MinIO client: %w". minio.New only fails when it cannot build a valid client from the inputs — most commonly an empty endpoint — since credentials are supplied as a static provider and no network I/O happens here.

Source

Thrown at internal/application/service/file/minio.go:43

}

// newMinioClient creates a bare minioFileService with just the SDK client initialised.
// Shared by NewMinioFileService (which also ensures the bucket exists) and
// CheckMinioConnectivity (read-only probe).
func newMinioClient(endpoint, accessKeyID, secretAccessKey, bucketName string, useSSL bool) (*minioFileService, error) {
	if err := utils.ValidateURLForSSRF(endpoint); err != nil {
		return nil, fmt.Errorf("unsafe MinIO endpoint: %w", err)
	}
	httpConfig := utils.DefaultSSRFSafeHTTPClientConfig()
	client, err := minio.New(endpoint, &minio.Options{
		Creds:  credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
		Secure: useSSL,
		Transport: &utils.SSRFValidatingRoundTripper{
			Base: utils.NewSSRFSafeTransport(httpConfig),
		},
	})
	if err != nil {
		return nil, fmt.Errorf("failed to initialize MinIO client: %w", err)
	}
	return &minioFileService{client: client, bucketName: bucketName}, nil
}

// NewMinioFileService creates a MinIO file service.
// It verifies that the bucket exists and creates it if missing.
func NewMinioFileService(endpoint,
	accessKeyID, secretAccessKey, bucketName string, useSSL bool,
) (interfaces.FileService, error) {
	svc, err := newMinioClient(endpoint, accessKeyID, secretAccessKey, bucketName, useSSL)
	if err != nil {
		return nil, err
	}

	exists, err := svc.client.BucketExists(context.Background(), bucketName)
	if err != nil {
		return nil, fmt.Errorf("failed to check bucket: %w", err)
	}

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Ensure MINIO_ENDPOINT is a non-empty host (optionally host:port) with no scheme or path, e.g. minio.example.com:9000, and restart the service
  2. Print the wrapped error (errors.Unwrap / %v) to see minio-go's exact parse message and correct the value
  3. Strip quotes/whitespace from the env value in your shell/compose file (use MINIO_ENDPOINT=minio:9000 without surrounding quotes inside YAML values where they become literal)
  4. Note that empty access/secret keys do NOT fail here (static credentials are accepted); if credentials are the concern, the failure will surface later at BucketExists, not at client init

Example fix

// before
MINIO_ENDPOINT="http://minio:9000/"  // scheme+path confuse minio.New
// after
MINIO_ENDPOINT=minio:9000  # host[:port] only; scheme controlled by useSSL flag
Defensive patterns

Strategy: validation

Validate before calling

func validateEndpointFormat(endpoint string) error {
    if strings.TrimSpace(endpoint) == "" {
        return fmt.Errorf("MINIO_ENDPOINT is empty")
    }
    if strings.HasPrefix(endpoint, "http://") || strings.HasPrefix(endpoint, "https://") || strings.Contains(endpoint, "/") {
        return fmt.Errorf("endpoint must be host[:port] only, no scheme or path: %q", endpoint)
    }
    host, port, err := net.SplitHostPort(endpoint)
    if err != nil {
        host = endpoint // port optional
    } else if _, err := strconv.Atoi(port); err != nil {
        return fmt.Errorf("invalid port %q", port)
    }
    if host == "" {
        return fmt.Errorf("endpoint missing host: %q", endpoint)
    }
    return nil
}

Try / catch

svc, err := file.NewMinioFileService(endpoint, ak, sk, bucket, useSSL)
if err != nil && strings.Contains(err.Error(), "failed to initialize MinIO client") {
    return fmt.Errorf("bad MINIO_ENDPOINT %q (want host[:port]): %w", endpoint, err)
} else if err != nil {
    return err
}

Prevention

When it happens

Trigger: minio.New(endpoint, &minio.Options{...}) returns an error, which in minio-go/v7 happens when the endpoint string is empty or cannot be parsed into a valid host:port pair (e.g. MINIO_ENDPOINT unset, contains only a scheme, or has illegal characters).

Common situations: MINIO_ENDPOINT environment variable not set in the deployment; trailing slash or embedded path in the endpoint value; endpoint copied with "http://" plus a path like /minio that the SDK cannot parse; whitespace or quotes accidentally included in the env value.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/9cbdbcf5a5b4757d. Report an issue: GitHub.