Billionmail/BillionMail · error
failed to check unsubscribe: %w
Error message
failed to check unsubscribe: %w
What it means
rebuildPostfixServiceNetworks found a 'services' map in the parsed compose config but no 'postfix-billionmail' key (or it is not a map). It is the typed-parsed counterpart of the text-scanner error of the same message.
Source
Thrown at core/internal/controller/batch_mail/batch_mail_v1_api_mail_send.go:212
"name": apiGroupName,
"description": fmt.Sprintf(public.LangCtx(ctx, "API %d automatically created contact group"), apiId),
"create_time": now,
"update_time": now,
})
if err != nil {
return contact, err
}
groupId, _ := groupResult.LastInsertId()
group.Id = int(groupId)
} else {
count, err := g.DB().Model("bm_contacts").
Where("email", email).
Where("group_id", group.Id).
Where("active", 0).
Count()
if err != nil {
return contact, fmt.Errorf("failed to check unsubscribe: %w", err)
}
if count > 0 {
return contact, fmt.Errorf("the recipient has unsubscribed from the current group and cannot send")
}
}
contactData := g.Map{
"email": email,
"group_id": group.Id,
"active": 1,
"status": 1,
"create_time": now,
}
contactResult, err := g.DB().Model("bm_contacts").
Data(contactData).
OnConflict("email,group_id").
Save()
if err != nil {View on GitHub (pinned to fc36c76c05)
Solutions
- Ensure 'services' contains an entry keyed exactly 'postfix-billionmail' before rebuilding
- If the service is declared in an override file, load/merge it into the config map passed to the function
- Rename the service back to 'postfix-billionmail' or adapt the code's service key
- Verify the parsed config: log config["services"] keys to confirm what the parser saw
Example fix
// before
services:
mail: {image: billionmail/postfix}
// after
services:
postfix-billionmail: {image: billionmail/postfix} Defensive patterns
Strategy: validation
Validate before calling
services, _ := cfg["services"].(map[string]interface{})
if _, ok := services["postfix-billionmail"].(map[string]interface{}); !ok {
return fmt.Errorf("postfix-billionmail service missing from parsed config")
} Type guard
func getPostfixService(cfg map[string]interface{}) (map[string]interface{}, bool) {
svc, _ := cfg["services"].(map[string]interface{})
p, ok := svc["postfix-billionmail"].(map[string]interface{})
return p, ok
} Try / catch
if err := m.rebuildPostfixServiceNetworks(cfg, configs); err != nil {
if strings.Contains(err.Error(), "postfix-billionmail service not found") {
// merge override files or restore the stock service block
}
return err
} Prevention
- Keep the service key 'postfix-billionmail' unrenamed in all compose files
- When using override files, merge them into the config before programmatic edits
- Grep the compose file for 'postfix-billionmail:' as a preflight check
- Avoid ad-hoc edits during deployment; use the official installer flow
When it happens
Trigger: Rebuild is invoked against a compose config where services exists but does not include a mapping named 'postfix-billionmail' — renamed service, wrong file, or service defined only in an override file not merged into the parsed config.
Common situations: Customized compose files with renamed mail service; parsing only the base file when the service is added in docker-compose.override.yml; typos in the service name.
Related errors
- failed to convert overview data: %v
- Not suppliers found
- Model not found
- failed to query group: %w
- the recipient has unsubscribed from the current group and ca
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/69817a64745ce337.
Report an issue: GitHub.