Billionmail/BillionMail · error
failed to query group: %w
Error message
failed to query group: %w
What it means
rebuildPostfixServiceNetworks operates on the docker-compose config parsed into a map and requires a top-level 'services' key of type map[string]interface{}. It throws this error when the key is absent or has a different type (e.g. null, a list), meaning the YAML is not a valid compose file structure.
Source
Thrown at core/internal/controller/batch_mail/batch_mail_v1_api_mail_send.go:189
if err != nil || emailTemplate.Id == 0 {
return nil, gerror.New(public.LangCtx(ctx, "Email template does not exist"))
}
return &emailTemplate, nil
}
// ensure contact and group exists
func ensureContactAndGroup(ctx context.Context, email string, apiId int) (entity.Contact, error) {
var contact entity.Contact
now := int(time.Now().Unix())
apiGroupName := fmt.Sprintf("api_group_%d", apiId)
var group entity.ContactGroup
err := g.DB().Model("bm_contact_groups").Where("name", apiGroupName).Scan(&group)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
group = entity.ContactGroup{}
} else {
return contact, fmt.Errorf("failed to query group: %w", err)
}
}
if group.Id == 0 {
groupResult, err := g.DB().Model("bm_contact_groups").Insert(g.Map{
"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).View on GitHub (pinned to fc36c76c05)
Solutions
- Validate the docker-compose.yml has a top-level 'services:' mapping before calling the rebuild
- Fix YAML syntax errors so 'services' parses as a map — inspect the parsed config with a debug dump
- Point the ConfigManager at the correct compose file (the main BillionMail one)
- Restore the original BillionMail docker-compose.yml
Example fix
# before (empty/broken file)
# (no services key)
# after
services:
postfix-billionmail:
image: billionmail/postfix Defensive patterns
Strategy: validation
Validate before calling
cfg, err := parseYAML(composePath)
if err != nil { return err }
services, ok := cfg["services"].(map[string]interface{})
if !ok || len(services) == 0 {
return fmt.Errorf("docker-compose.yml has no services mapping")
} Type guard
func hasServicesMap(cfg map[string]interface{}) bool {
m, ok := cfg["services"].(map[string]interface{})
return ok && m != nil
} Try / catch
if err := m.rebuildPostfixServiceNetworks(cfg, configs); err != nil {
if strings.Contains(err.Error(), "missing 'services'") {
// reload/repair the compose file before retrying
}
return err
} Prevention
- Run 'docker compose config -q' after any manual YAML edit
- Keep atomic writes (write temp file + rename) so compose files are never truncated
- Snapshot the compose file before programmatic modification
- Verify the parsed map is non-empty before rebuilding
When it happens
Trigger: Calling rebuildPostfixServiceNetworks with a config map parsed from a YAML file that lacks 'services' or where 'services' is not a mapping (empty file, malformed YAML that decodes to nil, wrong file passed).
Common situations: Empty or corrupt docker-compose.yml, a YAML file that parsed 'services' as something other than a map, or passing a partial config fragment instead of a full compose document.
Related errors
- the recipient has unsubscribed from the current group and ca
- Not suppliers found
- Model not found
- failed to check unsubscribe: %w
- failed to convert overview data: %v
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/516b23f48301afce.
Report an issue: GitHub.