Billionmail/BillionMail · error
failed to read temporary docker-compose.yml file: file is em
Error message
failed to read temporary docker-compose.yml file: file is empty or does not exist
What it means
After copying docker-compose.yml to the host core-data dir via chroot cp, updateDockerCompose reads it back through the container-side mapped path with gfile.GetContents. If the content is empty (file missing or zero bytes), the volume mapping between the container path and the host path is assumed broken, and the compose update aborts (triggering rollback).
Source
Thrown at core/internal/service/multi_ip_domain/config_manager.go:196
}
defer dk.Close()
// Step 1: 复制宿主机的 docker-compose.yml 到宿主机的 core-data 目录
// 注意:这里目标路径使用宿主机的路径,因为 chroot /host_root 看到的是宿主机文件系
copyCmd := []string{
"/bin/sh", "-c",
fmt.Sprintf(`chroot /host_root cp "%s" "%s"`, originalPath, hostTempDockerComposePath),
}
result, err := dk.ExecHostCommand(ctx, copyCmd)
if err != nil || result.ExitCode != 0 {
return gerror.New("failed to copy original configuration file, please check path and permissions")
}
// Step 2: 从容器内路径读取复制的文件
// 由于文件映射,容器内可以通过映射路径读到刚才复制的文件
content := gfile.GetContents(tempDockerComposePath)
if content == "" {
return fmt.Errorf("failed to read temporary docker-compose.yml file: file is empty or does not exist")
}
// Cleanup temporary file
defer func() {
if gfile.Exists(tempDockerComposePath) {
os.Remove(tempDockerComposePath)
g.Log().Debugf(ctx, "Cleaned up temporary file: %s", tempDockerComposePath)
}
}()
g.Log().Debugf(ctx, "Successfully read docker-compose.yml file, size: %d bytes", len(content))
newContent, err := m.modifyDockerComposeText(ctx, content, configs)
if err != nil {
return fmt.Errorf("failed to modify docker-compose content: %v", err)
}
// Step 7: Write new file docker-compose_addnetwork.yml
tempOutputPath := filepath.Join(containerDataPath, "temp_docker-compose_addnetwork.yml")View on GitHub (pinned to fc36c76c05)
Solutions
- Verify the bind mount maps host core-data to the container path returned by public.AbsPath('../core/data') (docker inspect the service).
- Check that docker-compose.yml on the host is non-empty and readable (wc -c /opt/billionmail/docker-compose.yml).
- Re-run the copy manually: chroot /host_root cp <compose> <core-data>/temp_docker-compose.yml and inspect the result.
- Add fsync/size verification after cp, and report the host path in the error to ease debugging.
Example fix
// before
content := gfile.GetContents(tempDockerComposePath)
if content == "" {
return fmt.Errorf("failed to read temporary docker-compose.yml file: file is empty or does not exist")
}
// after
content := gfile.GetContents(tempDockerComposePath)
if content == "" {
return fmt.Errorf("failed to read temporary docker-compose.yml at %s (host path %s): empty or missing; check volume mapping", tempDockerComposePath, hostTempDockerComposePath)
} Defensive patterns
Strategy: validation
Validate before calling
// preflight: verify host↔container mapping
hostCompose := filepath.Join(public.HostWorkDir, "docker-compose.yml")
fi, err := os.Stat(hostCompose)
if err != nil || fi.Size() == 0 {
return fmt.Errorf("docker-compose.yml missing or empty on host")
}
if _, err := os.Stat(filepath.Join(public.HostWorkDir, "core-data")); err != nil {
return fmt.Errorf("core-data bind mount missing")
} Try / catch
if err := mgr.ApplyConfigsWithRollback(ctx, configs); err != nil {
if strings.Contains(err.Error(), "file is empty or does not exist") {
// inspect docker volume mounts; temp copy never appeared via the mapping
}
} Prevention
- Confirm the bind mount source matches the container path computed by AbsPath.
- Verify docker-compose.yml is non-empty before applying.
- Use consistent mount propagation (rshared) if on network storage.
- Log both container and host temp paths on failure.
When it happens
Trigger: gfile.GetContents(tempDockerComposePath) returns "": the chroot cp wrote to the host path but ../core/data is not volume-mounted to host core-data, the copy raced/silently failed, or the source docker-compose.yml itself is empty.
Common situations: Deployment where the host bind mount path differs from what public.HostWorkDir expects; Docker volume remapped or renamed; docker-compose.yml truncated to 0 bytes on the host; propagation delay on network filesystems between cp and read.
Related errors
- failed to write temporary output file: %v
- project configuration file does not exist: %s
- error reading project configuration file: %v
- error writing project configuration file: %v
- error creating project configuration: %v
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/70e8aa02fb1f52be.
Report an issue: GitHub.