flipped-aurora/gin-vue-admin · error

删除新建文件 %s 失败: %w

Error message

删除新建文件 %s 失败: %w

What it means

When rolling back a file that did not exist before the task (file.Existed == false), rollback deletes it. If os.Remove fails with any error other than ErrNotExist, the removal failed and rollback aborts with this wrapped error naming the path.

Source

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

	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
		}
		if file.Existed && exists && currentHash == file.BeforeHash {
			continue
		}
		if !exists || currentHash != file.AfterHash {
			return fmt.Errorf("%w: %s", errAutoCodeFileConflict, file.TargetPath)
		}
		if !file.Existed {
			if err = os.Remove(file.TargetPath); err != nil && !errors.Is(err, fs.ErrNotExist) {
				return fmt.Errorf("删除新建文件 %s 失败: %w", file.TargetPath, err)
			}
			continue
		}
		if err = replaceAutoCodeFileAtomically(file.TargetPath, file.BeforeContent, file.Mode); err != nil {
			return fmt.Errorf("恢复自动代码文件 %s 失败: %w", file.TargetPath, err)
		}
	}
	return nil
}

func (task *autoCodeFileTask) cleanup() {
	if task != nil && task.stagingDir != "" {
		_ = os.RemoveAll(task.stagingDir)
		task.stagingDir = ""
	}
}

func joinAutoCodeRollbackError(cause, rollbackErr error) error {

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Fix permissions on the file and its parent directory so the server process can delete it (chown/chmod or run as the owning user)
  2. Close programs holding the file open (editors, `go run`, nodemon/vite watchers) and retry
  3. Check that the path is still a regular file, not a directory, and remove the intruding entry manually
  4. On Windows, ensure the file isn't read-only (clear the read-only attribute)

Example fix

// before
-rw-r--r-- 1 root root api.go   # server runs as www-data
// after
sudo chown www-data:www-data server/api/v1/api.go
Defensive patterns

Strategy: validation

Validate before calling

if err := unix.Access(dir, unix.W_OK); err != nil {
    return fmt.Errorf("cannot delete in %s: %w", dir, err)
}
// and verify target is a regular file
st, err := os.Stat(targetPath)
if err == nil && !st.Mode().IsRegular() {
    return fmt.Errorf("%s is not a regular file", targetPath)
}

Try / catch

if err := commitAutoCodeFileTask(task, publish, persist); err != nil {
    if strings.Contains(err.Error(), "删除新建文件") {
        var path string
        fmt.Sscanf(err.Error(), "删除新建文件 %s 失败", &path)
        fmt.Printf("manually remove %s after fixing permissions\n", path)
    }
}

Prevention

When it happens

Trigger: os.Remove(newFile) returns a real error during rollback — typically EACCES/EPERM (file or containing directory not writable by the process), EBUSY (file held open/locked on Windows), or the path turned into a directory.

Common situations: Server process lacks write permission on the generated directory (e.g. root-created files, read-only mount), Windows locks the file while a watcher/editor has it open, or the target was replaced by a directory between apply and rollback.

Related errors


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