{"record":{"id":"80cf73b1e7d3d8fa","repo":"Billionmail/BillionMail","slug":"failed-to-modify-docker-compose-content-v","errorCode":null,"errorMessage":"failed to modify docker-compose content: %v","messagePattern":"failed to modify docker-compose content: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/multi_ip_domain/config_manager.go","lineNumber":210,"sourceCode":"\t// Step 2: 从容器内路径读取复制的文件\n\t// 由于文件映射，容器内可以通过映射路径读到刚才复制的文件\n\tcontent := gfile.GetContents(tempDockerComposePath)\n\tif content == \"\" {\n\t\treturn fmt.Errorf(\"failed to read temporary docker-compose.yml file: file is empty or does not exist\")\n\t}\n\n\t// Cleanup temporary file\n\tdefer func() {\n\t\tif gfile.Exists(tempDockerComposePath) {\n\t\t\tos.Remove(tempDockerComposePath)\n\t\t\tg.Log().Debugf(ctx, \"Cleaned up temporary file: %s\", tempDockerComposePath)\n\t\t}\n\t}()\n\n\tg.Log().Debugf(ctx, \"Successfully read docker-compose.yml file, size: %d bytes\", len(content))\n\tnewContent, err := m.modifyDockerComposeText(ctx, content, configs)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to modify docker-compose content: %v\", err)\n\t}\n\n\t// Step 7: Write new file docker-compose_addnetwork.yml\n\ttempOutputPath := filepath.Join(containerDataPath, \"temp_docker-compose_addnetwork.yml\")\n\thostTempOutputPath := filepath.Join(hostDataPath, \"temp_docker-compose_addnetwork.yml\")\n\n\t// First write to temporary container file\n\tif err := gfile.PutContents(tempOutputPath, newContent); err != nil {\n\t\treturn fmt.Errorf(\"failed to write temporary output file: %v\", err)\n\t}\n\n\t// 然后从宿主机临时位置复制到最终目标位置\n\tcopyOutputCmd := []string{\n\t\t\"/bin/sh\", \"-c\",\n\t\tfmt.Sprintf(`chroot /host_root cp \"%s\" \"%s\"`, hostTempOutputPath, outputPath),\n\t}\n\n\tresult, err = dk.ExecHostCommand(ctx, copyOutputCmd)","sourceCodeStart":192,"sourceCodeEnd":228,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/multi_ip_domain/config_manager.go#L192-L228","documentation":"modifyDockerComposeText rewrites the networks section of docker-compose.yml and the postfix service networks as text. If adding custom networks or rewriting the postfix service networks fails (unexpected compose structure), this wrapper aborts the update and triggers Postfix config rollback. The root cause is the inner addCustomNetworksText/modifyPostfixNetworksText error.","triggerScenarios":"modifyDockerComposeText returns error: services/networks section missing from the compose text, indentation/structure not matching the parser's expectations, or invalid config entries (bad network name/IP).","commonSituations":"Users customized docker-compose.yml (comments removed sections, changed formatting) so the text rewriter can't locate the postfix-billionmail service or networks key; config payload has malformed network names.","solutions":["Read the inner error to see which rewrite step failed (addCustomNetworksText vs modifyPostfixNetworksText).","Restore a stock docker-compose.yml with standard services/networks sections and default formatting, then retry.","Validate network names/IPs in the configs payload (lowercase alphanumerics/dashes, valid IPs).","Keep the compose file close to the generated template; avoid restructuring sections this rewriter depends on."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"content, _ := os.ReadFile(filepath.Join(public.HostWorkDir, \"docker-compose.yml\"))\nif !strings.Contains(string(content), \"services:\") || !strings.Contains(string(content), \"networks:\") {\n\treturn fmt.Errorf(\"docker-compose.yml missing services/networks sections; restore stock layout\")\n}\nif !strings.Contains(string(content), \"postfix-billionmail\") {\n\treturn fmt.Errorf(\"postfix-billionmail service not found in compose file\")\n}","typeGuard":null,"tryCatchPattern":"if err := mgr.ApplyConfigsWithRollback(ctx, configs); err != nil {\n\tif strings.Contains(err.Error(), \"failed to modify docker-compose content\") {\n\t\t// restore a standard compose file and validate network names before retry\n\t}\n}","preventionTips":["Keep docker-compose.yml structure close to the stock template.","Validate network names (lowercase, [a-z0-9-]) in configs.","Diff compose changes through the tool rather than manual restructuring.","Keep the compose file valid YAML-parseable at all times."],"tags":["docker-compose","yaml","parsing","go"],"backgroundTag":"docker-compose-modify-failed","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"}