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

  1. Verify the bind mount maps host core-data to the container path returned by public.AbsPath('../core/data') (docker inspect the service).
  2. Check that docker-compose.yml on the host is non-empty and readable (wc -c /opt/billionmail/docker-compose.yml).
  3. Re-run the copy manually: chroot /host_root cp <compose> <core-data>/temp_docker-compose.yml and inspect the result.
  4. 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

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


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/70e8aa02fb1f52be. Report an issue: GitHub.