flipped-aurora/gin-vue-admin · error

[filepath:%s]打开文件失败!

Error message

[filepath:%s]打开文件失败!

What it means

Base.Format writes the (modified) AST back to disk. Before format.Node runs it opens the target file with os.OpenFile(O_WRONLY|O_TRUNC); if the file cannot be opened it wraps the OS error with this message. The underlying cause (ENOENT, EACCES, EISDIR) is preserved in the wrapped chain.

Source

Thrown at server/utils/ast/interfaces_base.go:51

func (a *Base) Rollback(file *ast.File) error {
	return nil
}

func (a *Base) Injection(file *ast.File) error {
	return nil
}

func (a *Base) Format(filename string, writer io.Writer, file *ast.File) error {
	fileSet := a.FileSet
	if fileSet == nil {
		fileSet = token.NewFileSet()
	}
	if writer == nil {
		open, err := os.OpenFile(filename, os.O_WRONLY|os.O_TRUNC, 0666)
		defer open.Close()
		if err != nil {
			return errors.Wrapf(err, "[filepath:%s]打开文件失败!", filename)
		}
		writer = open
	}
	err := format.Node(writer, fileSet, file)
	if err != nil {
		return errors.Wrapf(err, "[filepath:%s]注入失败!", filename)
	}
	return nil
}

// RelativePath 绝对路径转相对路径
func (a *Base) RelativePath(filePath string) string {
	server := filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server)
	hasServer := strings.Index(filePath, server)
	if hasServer != -1 {
		filePath = strings.TrimPrefix(filePath, server)
		keys := strings.Split(filePath, string(filepath.Separator))
		filePath = path.Join(keys...)

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Verify the filepath exists and is writable (ls -l, touch the file as the same user)
  2. Grant write permission: chmod/chown the file or run the generator with adequate privileges
  3. Ensure the file is not deleted/renamed between Parse and Format in your pipeline
  4. Re-run the generation step

Example fix

// before
err := base.Format("gen/removed.go", file) // ENOENT
// after
if _, statErr := os.Stat("gen/removed.go"); statErr != nil { os.Create("gen/removed.go") }
err := base.Format("gen/removed.go", file)
Defensive patterns

Strategy: validation

Validate before calling

info, err := os.Stat(filename); if err != nil || info.IsDir() { return fmt.Errorf("cannot format %s: %w", filename, err) }; if info.Mode().Perm()&0200 == 0 { return fmt.Errorf("%s is not writable", filename) }

Try / catch

if err := base.Format(filename, file); err != nil { var pe *fs.PathError; if errors.As(err, &pe) { log.Printf("cannot open %s: %v", filename, pe) }; return err }

Prevention

When it happens

Trigger: Calling Base.Format(filename, file) when the target file was deleted or moved between Parse and Format, the process lacks write permission, or filename points to a directory; also when the nil-writer branch runs against a nonexistent path.

Common situations: Code generator run against a stale path after a refactor; read-only checkout or mounted volume; SELinux/container permissions; file locked by another process is rare on Linux but permission issues are common in Docker builds.

Related errors


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