Billionmail/BillionMail · error

failed to convert overview data: %v

Error message

failed to convert overview data: %v

What it means

After querying the overview statistics, FailedList uses goframe's gconv.Struct to map the service result into the response Data struct. If the conversion fails — mismatched field types, nil/incompatible structures — the raw conversion error is wrapped with this message.

Source

Thrown at core/internal/controller/overview/overview_v1_failed_list.go:32

func (c *ControllerV1) FailedList(ctx context.Context, req *v1.FailedListReq) (res *v1.FailedListRes, err error) {
	res = &v1.FailedListRes{}

	if req.EndTime == 0 {
		req.EndTime = time.Now().Unix()
	}

	if req.EndTime < req.StartTime {
		err = fmt.Errorf("start time must be greater or equal to end time")
		return
	}

	overview := maillog_stat.NewOverview()
	failedList := overview.FailedList(req.CampaignId, req.Domain, req.StartTime, req.EndTime)

	err = gconv.Struct(failedList, &res.Data)

	if err != nil {
		err = fmt.Errorf("failed to convert overview data: %v", err)
		return
	}

	res.SetSuccess(public.LangCtx(ctx, "Success"))

	return
}

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Inspect the wrapped %v detail to see which field failed conversion
  2. Align the service return struct and res.Data field names/types (use pointers for nullable DB columns)
  3. Add unit tests covering the conversion with realistic service output
  4. If the source data may be absent, guard for empty/nil before calling gconv.Struct

Example fix

// before
type failedItem struct { Count int `json:"count"` }
// DB may return NULL
// after
type failedItem struct { Count *int `json:"count"` }
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure expected fields are present in the response before conversion
const shapeOk = r && typeof r === 'object' && 'items' in r;

Type guard

function isFailedListShape(x: unknown): x is Record<string, unknown> {
  return typeof x === 'object' && x !== null && !Array.isArray(x);
}

Try / catch

try {
  const data = await api.failedList(params);
} catch (err) {
  if (String(err.message).startsWith('failed to convert overview data')) {
    console.error('Service/controller contract drift:', err);
    // surface a backend-schema bug report
  }
}

Prevention

When it happens

Trigger: maillog_stat Overview().FailedList returning a shape (map or struct) whose fields cannot be converted into res.Data's type: e.g. numeric fields returned as strings that fail parsing, changed service return type after a refactor, or a nil result being converted.

Common situations: Schema drift between service and controller structs after code changes; DB returning NULLs into non-pointer numeric fields; version skew where an older service returns a different field set than the controller expects.

Related errors


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