Billionmail/BillionMail · warning

failed to parse alert settings: %v

Error message

failed to parse alert settings: %v

What it means

loadBlacklistAlertSettingsForAlert unmarshals the file contents into the BlacklistAlertSettings struct; any json.Unmarshal error (malformed JSON, wrong types, invalid syntax) is wrapped as 'failed to parse alert settings: %v'. The %v carries the encoding/json detail such as the byte offset and expected type.

Source

Thrown at core/internal/service/domains/blacklist.go:468

	RecipientList []string `json:"recipient_list"`
}

func loadBlacklistAlertSettingsForAlert() (*BlacklistAlertSettings, error) {
	alertSettingsFile := public.AbsPath("../core/data/blacklist_alert_settings.json")

	if !gfile.Exists(alertSettingsFile) {
		return nil, fmt.Errorf("alert settings file not found")
	}

	content := gfile.GetContents(alertSettingsFile)
	if content == "" {
		return nil, fmt.Errorf("alert settings file is empty")
	}

	var settings BlacklistAlertSettings
	err := json.Unmarshal([]byte(content), &settings)
	if err != nil {
		return nil, fmt.Errorf("failed to parse alert settings: %v", err)
	}

	return &settings, nil
}

func sendAlertEmail(ctx context.Context, settings *BlacklistAlertSettings, subject, body string) error {

	sender := mail_service.NewEmailSender()
	sender.Host = settings.SMTPServer
	sender.Port = fmt.Sprintf("%d", settings.SMTPPort)
	sender.Email = settings.SenderEmail
	sender.UserName = settings.SenderEmail
	sender.Password = settings.SMTPPassword

	err := sender.Connect()
	if err != nil {
		return fmt.Errorf("failed to connect to SMTP server: %v", err)
	}

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Validate the JSON: jq . ../core/data/blacklist_alert_settings.json and fix the reported offset error
  2. Re-save settings via the admin UI to regenerate a schema-correct file
  3. Compare the file against the BlacklistAlertSettings struct fields/types in the current code version
  4. Write settings atomically (temp file + rename) to prevent partial JSON on crash

Example fix

// before
err := json.Unmarshal([]byte(content), &settings)
if err != nil {
	return nil, fmt.Errorf("failed to parse alert settings: %v", err)
}
// after
err := json.Unmarshal([]byte(content), &settings)
if err != nil {
	return nil, fmt.Errorf("failed to parse alert settings from %s: %w", alertSettingsFile, err)
}
Defensive patterns

Strategy: validation

Validate before calling

content := gfile.GetContents(settingsPath)
var probe map[string]any
if err := json.Unmarshal([]byte(content), &probe); err != nil {
	return fmt.Errorf("alert settings JSON invalid: %w", err)
}

Type guard

func validBlacklistAlertSettings(b []byte) bool {
	var s BlacklistAlertSettings
	return json.Unmarshal(b, &s) == nil
}

Try / catch

settings, err := loadBlacklistAlertSettingsForAlert()
var perr *json.SyntaxError
if err != nil && errors.As(err, perr) {
	// report perr.Offset so the admin can fix the exact spot in the JSON
}

Prevention

When it happens

Trigger: sendBlacklistAlert runs while blacklist_alert_settings.json contains syntactically invalid JSON or fields whose types don't match the struct (e.g. a string where RecipientList expects an array, trailing commas, single quotes, BOM, or comments).

Common situations: Hand-edited settings file with a syntax mistake; concurrent writes producing interleaved/partial JSON; older schema file no longer matching the struct after an upgrade; file corrupted by a crash mid-write.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


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