{"record":{"id":"69817a64745ce337","repo":"Billionmail/BillionMail","slug":"failed-to-check-unsubscribe-w","errorCode":null,"errorMessage":"failed to check unsubscribe: %w","messagePattern":"failed to check unsubscribe: %w","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/controller/batch_mail/batch_mail_v1_api_mail_send.go","lineNumber":212,"sourceCode":"\t\t\t\"name\":        apiGroupName,\n\t\t\t\"description\": fmt.Sprintf(public.LangCtx(ctx, \"API %d automatically created contact group\"), apiId),\n\t\t\t\"create_time\": now,\n\t\t\t\"update_time\": now,\n\t\t})\n\t\tif err != nil {\n\t\t\treturn contact, err\n\t\t}\n\t\tgroupId, _ := groupResult.LastInsertId()\n\t\tgroup.Id = int(groupId)\n\t} else {\n\n\t\tcount, err := g.DB().Model(\"bm_contacts\").\n\t\t\tWhere(\"email\", email).\n\t\t\tWhere(\"group_id\", group.Id).\n\t\t\tWhere(\"active\", 0).\n\t\t\tCount()\n\t\tif err != nil {\n\t\t\treturn contact, fmt.Errorf(\"failed to check unsubscribe: %w\", err)\n\t\t}\n\t\tif count > 0 {\n\t\t\treturn contact, fmt.Errorf(\"the recipient has unsubscribed from the current group and cannot send\")\n\t\t}\n\t}\n\n\tcontactData := g.Map{\n\t\t\"email\":       email,\n\t\t\"group_id\":    group.Id,\n\t\t\"active\":      1,\n\t\t\"status\":      1,\n\t\t\"create_time\": now,\n\t}\n\tcontactResult, err := g.DB().Model(\"bm_contacts\").\n\t\tData(contactData).\n\t\tOnConflict(\"email,group_id\").\n\t\tSave()\n\tif err != nil {","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/controller/batch_mail/batch_mail_v1_api_mail_send.go#L194-L230","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nservices:\n  mail: {image: billionmail/postfix}\n// after\nservices:\n  postfix-billionmail: {image: billionmail/postfix}","handlingStrategy":"validation","validationCode":"services, _ := cfg[\"services\"].(map[string]interface{})\nif _, ok := services[\"postfix-billionmail\"].(map[string]interface{}); !ok {\n\treturn fmt.Errorf(\"postfix-billionmail service missing from parsed config\")\n}","typeGuard":"func getPostfixService(cfg map[string]interface{}) (map[string]interface{}, bool) {\n\tsvc, _ := cfg[\"services\"].(map[string]interface{})\n\tp, ok := svc[\"postfix-billionmail\"].(map[string]interface{})\n\treturn p, ok\n}","tryCatchPattern":"if err := m.rebuildPostfixServiceNetworks(cfg, configs); err != nil {\n\tif strings.Contains(err.Error(), \"postfix-billionmail service not found\") {\n\t\t// merge override files or restore the stock service block\n\t}\n\treturn err\n}","preventionTips":["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"],"tags":["docker-compose","multi-ip","yaml","service-key"],"backgroundTag":"service-not-found-in-compose","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}