flipped-aurora/gin-vue-admin · error

创建目标目录 %s 失败: %w

Error message

创建目标目录 %s 失败: %w

What it means

Raised when creating the parent directory of a publish target with os.MkdirAll(dir, 0o755) fails. The task creates missing target directories just-in-time before the atomic rename so that new generated files nested in new packages/views can be placed; any MkdirAll error (other than the directory already existing, which MkdirAll tolerates) aborts the file publish.

Source

Thrown at server/service/system/auto_code_task.go:206

}

func publishPreparedAutoCodeFile(file *autoCodeTaskFile) (bool, error) {
	currentHash, exists, err := hashAutoCodeTarget(file.TargetPath)
	if err != nil {
		return false, err
	}
	if exists && currentHash == file.AfterHash {
		if removeErr := os.Remove(file.StagedPath); removeErr != nil && !errors.Is(removeErr, fs.ErrNotExist) {
			return false, fmt.Errorf("清理重复 staging 文件失败: %w", removeErr)
		}
		file.StagedPath = ""
		return false, nil
	}
	if exists != file.Existed || (file.Existed && currentHash != file.BeforeHash) {
		return false, fmt.Errorf("%w: %s", errAutoCodeFileConflict, file.TargetPath)
	}
	if err = os.MkdirAll(filepath.Dir(file.TargetPath), 0o755); err != nil {
		return false, fmt.Errorf("创建目标目录 %s 失败: %w", filepath.Dir(file.TargetPath), err)
	}
	if err = os.Rename(file.StagedPath, file.TargetPath); err != nil {
		return false, fmt.Errorf("原子发布 %s 失败: %w", file.TargetPath, err)
	}
	file.StagedPath = ""
	return true, nil
}

func (task *autoCodeFileTask) rollback(applied []int) error {
	for i := len(applied) - 1; i >= 0; i-- {
		index := applied[i]
		if index < 0 || index >= len(task.files) {
			return fmt.Errorf("自动代码回滚索引无效: %d", index)
		}
		file := &task.files[index]
		currentHash, exists, err := hashAutoCodeTarget(file.TargetPath)
		if err != nil {
			return err

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Check that the parent path of the reported directory is writable by the server process (permissions, ownership)
  2. Ensure no regular file exists at a path component that must be a directory (remove/rename it)
  3. If deployed in a container, mount the server/ and web/ trees read-write
  4. Check disk space (df -h) and mandatory access control logs (SELinux/AppArmor) if errors persist

Example fix

// before: read-only code mount in container
volumes:
  - ./web:/app/web:ro

// after: make writable
volumes:
  - ./web:/app/web:rw
Defensive patterns

Strategy: validation

Validate before calling

func ensureTargetDirsWritable(targets []string) error {
	seen := map[string]bool{}
	for _, t := range targets {
		dir := filepath.Dir(t)
		if seen[dir] {
			continue
		}
		seen[dir] = true
		if info, err := os.Stat(dir); err == nil && !info.IsDir() {
			return fmt.Errorf("%s is a file, not a directory", dir)
		}
		// walk up to the first existing ancestor and test writability
		for d := dir; ; d = filepath.Dir(d) {
			if _, err := os.Stat(d); err == nil {
				if probe, perr := os.CreateTemp(d, ".w"); perr != nil {
					return fmt.Errorf("%s not writable: %w", d, perr)
				} else {
					probe.Close()
					os.Remove(probe.Name())
				}
				break
			}
		}
	}
	return nil
}

Try / catch

if err := commitAutoCodeFileTask(task, publishPreparedAutoCodeFile, persist); err != nil {
	var mkErr *fmt.WrapError // match on message prefix instead
	if strings.Contains(err.Error(), "创建目标目录") {
		log.Printf("cannot create target dir (check perms/disk/mounts): %v", err)
	}
}

Prevention

When it happens

Trigger: publishPreparedAutoCodeFile publishing a file whose target directory does not exist yet, and MkdirAll fails because a parent path component is not a directory, permissions deny creation, the filesystem is read-only/full, or the target path is invalid on the OS.

Common situations: Server runs without write permission on server/ or web/ trees (e.g. containerized deployment with read-only code volume); a file exists where a directory is needed; ENOSPC on disk; SELinux/AppArmor blocking writes in the project root.

Related errors


AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31). Data as JSON: /api/errors/a8e13b48d211e35e. Report an issue: GitHub.