{"record":{"id":"c9b55ad024e2c283","repo":"Tencent/WeKnora","slug":"failed-to-check-bucket-w","errorCode":null,"errorMessage":"failed to check bucket: %w","messagePattern":"failed to check bucket: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/application/service/file/minio.go","lineNumber":60,"sourceCode":"\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to initialize MinIO client: %w\", err)\n\t}\n\treturn &minioFileService{client: client, bucketName: bucketName}, nil\n}\n\n// NewMinioFileService creates a MinIO file service.\n// It verifies that the bucket exists and creates it if missing.\nfunc NewMinioFileService(endpoint,\n\taccessKeyID, secretAccessKey, bucketName string, useSSL bool,\n) (interfaces.FileService, error) {\n\tsvc, err := newMinioClient(endpoint, accessKeyID, secretAccessKey, bucketName, useSSL)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\texists, err := svc.client.BucketExists(context.Background(), bucketName)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to check bucket: %w\", err)\n\t}\n\tif !exists {\n\t\tif err = svc.client.MakeBucket(context.Background(), bucketName, minio.MakeBucketOptions{}); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to create bucket: %w\", err)\n\t\t}\n\t}\n\n\treturn svc, nil\n}\n\n// CheckConnectivity verifies MinIO is reachable and, if a bucket is configured,\n// that the bucket exists. This is a read-only probe — it never creates a bucket.\nfunc (s *minioFileService) CheckConnectivity(ctx context.Context) error {\n\tcheckCtx, cancel := context.WithTimeout(ctx, 10*time.Second)\n\tdefer cancel()\n\n\tif s.bucketName != \"\" {\n\t\texists, err := s.client.BucketExists(checkCtx, s.bucketName)","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/service/file/minio.go#L42-L78","documentation":"NewMinioFileService calls BucketExists on the freshly built minio-go client and wraps any transport/API error as \"failed to check bucket: %w\". Unlike the not-exists case (which triggers MakeBucket), this error means the existence check itself could not be completed — the SDK call returned a network, TLS, authentication, or S3 API error.","triggerScenarios":"svc.client.BucketExists(context.Background(), bucketName) returns an error: MinIO host unreachable (connection refused/DNS failure), TLS handshake failure when useSSL=true against a plaintext endpoint (or vice versa), invalid access/secret keys rejected by the server (SignatureDoesNotMatch/AccessDenied), or no network egress from the container.","commonSituations":"MinIO not yet started or wrong port in docker-compose; MINIO_USE_SSL=true while the server only serves HTTP (tls: first record does not look like a TLS handshake); wrong MINIO_ACCESS_KEY/SECRET_KEY; egress firewall or missing NetworkPolicy in Kubernetes; DNS name typo in the endpoint.","solutions":["Verify MinIO is reachable from the app: curl/nc the endpoint host:port from inside the container; fix the endpoint or start the MinIO service","Match the SSL setting to the server: set MINIO_USE_SSL=false for plain HTTP MinIO or true only when the server has TLS enabled (check for tls handshake errors in the wrapped cause)","Verify MINIO_ACCESS_KEY/MINIO_SECRET_KEY against the server's credentials (mc alias set + mc ls to test independently)","Check network egress: docker network, Kubernetes NetworkPolicy, or firewall rules may block port 9000","Retry with backoff if MinIO is starting concurrently (startup race in compose); consider readiness probes ordering"],"exampleFix":"// before (compose)\nMINIO_USE_SSL=true   # minio running without TLS -> handshake error\n// after\nMINIO_USE_SSL=false  # plain-HTTP local MinIO; enable TLS before flipping to true","handlingStrategy":"retry","validationCode":"conn, err := net.DialTimeout(\"tcp\", endpointHostPort, 3*time.Second)\nif err != nil {\n    return fmt.Errorf(\"MinIO endpoint %s unreachable before client init: %w\", endpointHostPort, err)\n}\nconn.Close()\nif useSSL {\n    // verify TLS works; a plaintext server will fail BucketExists\n    if _, err := tls.Dial(\"tcp\", endpointHostPort, nil); err != nil {\n        return fmt.Errorf(\"TLS handshake failed; check MINIO_USE_SSL: %w\", err)\n    }\n}","typeGuard":null,"tryCatchPattern":"svc, err := file.NewMinioFileService(endpoint, ak, sk, bucket, useSSL)\nif err != nil && strings.Contains(err.Error(), \"failed to check bucket\") {\n    // transient (MinIO starting up / network blip): retry with backoff\n    var re *minio.ErrorResponse\n    if errors.As(err, &re) && re.Code == \"SignatureDoesNotMatch\" {\n        return fmt.Errorf(\"bad MinIO credentials, do not retry: %w\", err)\n    }\n    return retry.WithBackoff(3, func() error {\n        svc, err = file.NewMinioFileService(endpoint, ak, sk, bucket, useSSL)\n        return err\n    })\n} else if err != nil {\n    return err\n}","preventionTips":["Add a readiness gate so the app starts only after MinIO accepts TCP connections","Keep MINIO_USE_SSL in sync with the server's TLS configuration","Test credentials with `mc alias set`/`mc ls` before deploying","Order docker-compose/Kubernetes startup so MinIO (with healthcheck) is ready before the app calls NewFileServiceFromStorageConfig"],"tags":["minio","network","tls","authentication","bucket"],"backgroundTag":"minio-bucket-check-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}