Billionmail/BillionMail · error

fail to check domain: %w

Error message

fail to check domain: %w

What it means

SetSSL wraps an error returned by domains.Exists(ctx, req.Domain) with 'fail to check domain: %w'. This is distinct from the 'domain does not exist' branch: it fires only when the existence check itself errored (usually a database failure), so the operation aborts before touching SSL config.

Source

Thrown at core/internal/controller/domains/domains_v1_set_ssl.go:19

package domains

import (
	"billionmail-core/internal/consts"
	"billionmail-core/internal/service/domains"
	"billionmail-core/internal/service/mail_service"
	"billionmail-core/internal/service/public"
	"context"
	"fmt"

	"billionmail-core/api/domains/v1"
)

func (c *ControllerV1) SetSSL(ctx context.Context, req *v1.SetSSLReq) (res *v1.SetSSLRes, err error) {
	res = &v1.SetSSLRes{}

	if ex, err1 := domains.Exists(ctx, req.Domain); !ex {
		if err1 != nil {
			res.SetError(fmt.Errorf("fail to check domain: %w", err1))
			return
		}

		res.SetError(fmt.Errorf("domain %s does not exist", req.Domain))
		return
	}

	crt := mail_service.NewCertificate()

	defer crt.Close()

	err = crt.SetSNI(public.FormatMX(req.Domain), req.Certificate, req.Key)

	if err != nil {
		res.SetError(fmt.Errorf("fail to set ssl: %w", err))
		return
	}

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Inspect the wrapped cause for the actual DB error and fix that first (connectivity, credentials, schema).
  2. Verify the database is healthy and reachable before retrying the SetSSL call.
  3. Confirm the domains table exists and migrations are current.
  4. Retry the request once the DB issue is resolved; the check is transient-failure prone, not a request-shape problem.
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight DB check
if err := gdb.Config().Master.Ping(); err != nil {
	return fmt.Errorf("database unreachable: %w", err)
}

Try / catch

_, err := client.SetSSL(ctx, req)
if err != nil {
	if strings.Contains(err.Error(), "fail to check domain") {
		return backoff.Retry(func() error {
			_, err = client.SetSSL(ctx, req)
			return err
		}, backoff.WithMaxRetries(backoff.NewExponentialBackOff(), 3))
	}
	return err
}

Prevention

When it happens

Trigger: domains.Exists(ctx, req.Domain) returns (ex=false, err1 != nil) — e.g. the SELECT against the domains table fails due to DB unavailability, timeout, or schema mismatch while handling a SetSSL request.

Common situations: Postgres down or unreachable during an SSL setup; wrong DB config after migration; query timeout on a large domains table; transient network error between app and database in Compose deployments.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/9b49cd461b96b3eb. Report an issue: GitHub.