antonmedv/fx · error

cannot save to a symbolic link: %s

Error message

cannot save to a symbolic link: %s

What it means

Refuses to persist output when the target FilePath is a symbolic link, detected via os.Lstat mode bits. This is a deliberate safety guard against accidentally overwriting a file the link points to; the save operation is aborted.

Source

Thrown at internal/engine/vm.go:35

	Code int
}

func NewVM(writeOut func(string)) *goja.Runtime {
	vm := goja.New()

	if err := vm.Set("println", func(s string) any {
		writeOut(s)
		return nil
	}); err != nil {
		panic(err)
	}

	if err := vm.Set("__save__", func(json string) error {
		if FilePath == "" {
			return fmt.Errorf("specify a file as the first argument to be able to save: fx file.json ")
		}
		if info, err := os.Lstat(FilePath); err == nil && info.Mode()&os.ModeSymlink != 0 {
			return fmt.Errorf("cannot save to a symbolic link: %s", FilePath)
		}
		if err := os.WriteFile(FilePath, []byte(json), 0644); err != nil {
			return err
		}
		return nil
	}); err != nil {
		panic(err)
	}

	if err := vm.Set("__stringify__", func(x goja.Value) string {
		return Stringify(x, vm, 0) + "\n"
	}); err != nil {
		panic(err)
	}

	if err := vm.Set("__toBase64__", func(x string) string {
		return base64.StdEncoding.EncodeToString([]byte(x))
	}); err != nil {

View on GitHub (pinned to 4f31cd3a0c)

Solutions

  1. Save to the real file path instead of the symlink
  2. Remove the symlink and use a regular file
  3. Run fx on the resolved target path directly
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at internal/engine/vm.go:35 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of antonmedv/fx@4f31cd3a0c (2026-09-02). Data as JSON: /api/errors/9ec005a4d2232321. Report an issue: GitHub.