Billionmail/BillionMail · error
failed to create temporary directory %s: %v
Error message
failed to create temporary directory %s: %v
What it means
updateDockerCompose needs the container-side data directory (../core/data) to stage temp copies of docker-compose.yml via the host volume mapping. If the directory does not exist and gfile.Mkdir cannot create it, this error aborts the compose update before any Docker command runs. It indicates a filesystem permission or path problem inside the container.
Source
Thrown at core/internal/service/multi_ip_domain/config_manager.go:171
}
// updateDockerCompose Generate docker-compose_addnetwork.yml
func (m *ConfigManager) updateDockerCompose(ctx context.Context, configs []map[string]interface{}) error {
originalPath := filepath.Join(public.HostWorkDir, "docker-compose.yml")
outputPath := filepath.Join(public.HostWorkDir, "docker-compose_addnetwork.yml")
// 设置临时文件路径
// 容器内路径:/opt/billionmail/core/data (通过 public.AbsPath 获取)
// 宿主机路径:./core-data (相对于 docker-compose.yml 所在目录)
containerDataPath := public.AbsPath("../core/data/")
hostDataPath := filepath.Join(public.HostWorkDir, "core-data") // 宿主机的实际映射路径
tempDockerComposePath := filepath.Join(containerDataPath, "temp_docker-compose.yml")
hostTempDockerComposePath := filepath.Join(hostDataPath, "temp_docker-compose.yml")
// Ensure container directory exists
if !gfile.Exists(containerDataPath) {
if err := gfile.Mkdir(containerDataPath); err != nil {
return fmt.Errorf("failed to create temporary directory %s: %v", containerDataPath, err)
}
}
dk, err := docker.NewDockerAPI()
if err != nil {
return gerror.New(public.LangCtx(ctx, "failed to create Docker API instance: %v", err.Error()))
}
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")View on GitHub (pinned to fc36c76c05)
Solutions
- Create the directory manually with correct ownership: mkdir -p <containerDataPath> && chown <process-user> <containerDataPath>.
- Use gfile.Mkdir (recursive) instead of single-level Mkdir so a missing parent does not abort.
- Verify the volume mount for core/data exists in docker-compose.yml and is writable.
- Confirm the process work directory is correct so AbsPath resolves the intended location.
Example fix
// before
if !gfile.Exists(containerDataPath) {
if err := gfile.Mkdir(containerDataPath); err != nil {
return fmt.Errorf("failed to create temporary directory %s: %v", containerDataPath, err)
}
}
// after
if !gfile.Exists(containerDataPath) {
if err := gfile.Mkdir(containerDataPath); err != nil {
return fmt.Errorf("failed to create temporary directory %s: %v", containerDataPath, err)
}
} Defensive patterns
Strategy: validation
Validate before calling
dir := public.AbsPath("../core/data")
if fi, err := os.Stat(dir); err != nil || !fi.IsDir() {
if err := os.MkdirAll(dir, 0o755); err != nil {
return fmt.Errorf("cannot prepare temp dir %s: %v", dir, err)
}
} Try / catch
if err := mgr.ApplyConfigsWithRollback(ctx, configs); err != nil {
if strings.Contains(err.Error(), "failed to create temporary directory") {
// mkdir the path manually with correct ownership, then retry
}
} Prevention
- Pre-create the core/data directory in the deployment image with correct ownership.
- Mount core/data rw in docker-compose.
- Use recursive Mkdir for nested paths.
- Verify AbsPath base directory at service startup.
When it happens
Trigger: gfile.Exists(containerDataPath) is false and gfile.Mkdir fails: parent dir missing, no write permission, read-only filesystem, or an invalid path component.
Common situations: Deployment where the core/data volume was pruned and the parent directory is root-owned; image runs as non-root; working directory moved so public.AbsPath('../core/data') resolves somewhere unwritable.
Related errors
- error reading project configuration file: %v
- error writing project configuration file: %v
- error writing knowledge base file: %v
- error removing knowledge base file: %v
- error creating company profile file: %v
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/ff8d47a1ba28b689.
Report an issue: GitHub.