hasura/graphql-engine · error

failed to remove the symlink in %q: %w

Error message

failed to remove the symlink in %q: %w

What it means

After removeLink confirms the target is a symlink, os.Remove is called to delete it; this error wraps any failure of that deletion. It usually means the containing directory is not writable (deleting a file requires write permission on its directory, not on the file itself) or the file vanished between Lstat and Remove.

Source

Thrown at cli/plugins/util.go:244

}

// removeLink removes a symlink reference if exists.
func removeLink(path string) error {
	var op errors.Op = "plugins.removeLink"

	fi, err := os.Lstat(path)
	if stderrors.Is(err, fs.ErrNotExist) {
		return nil
	} else if err != nil {
		return errors.E(op, fmt.Errorf("failed to read the symlink in %q: %w", path, err))
	}

	if fi.Mode()&os.ModeSymlink == 0 && !IsWindows() {
		return errors.E(op, fmt.Errorf("file %q is not a symlink (mode=%s)", path, fi.Mode()))
	}

	if err := os.Remove(path); err != nil {
		return errors.E(op, fmt.Errorf("failed to remove the symlink in %q: %w", path, err))
	}

	return nil
}

// PluginNameToBin creates the name of the symlink file for the plugin name.
// It converts dashes to underscores.
func PluginNameToBin(name string, isWindows bool) string {
	name = strings.ReplaceAll(name, "-", "_")

	name = "hasura-" + name
	if isWindows {
		name += ".exe"
	}

	return name
}

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Fix ownership/permissions of the bin directory: sudo chown -R $USER ~/.hasura/plugins && chmod u+w ~/.hasura/plugins/bin.
  2. Check for immutability: lsattr <path> and clear with chattr -i if set.
  3. Close processes holding the binary (or reboot on Windows) and retry the uninstall.
  4. Retry the command if the link was concurrently removed (race).
Defensive patterns

Strategy: retry

Validate before calling

// ensure the containing directory is writable before uninstall
if info, err := os.Stat(filepath.Dir(linkPath)); err == nil {
    if info.Mode().Perm()&0o200 == 0 { os.Chmod(filepath.Dir(linkPath), 0o755) }
}

Try / catch

err := uninstall()
if err != nil && strings.Contains(err.Error(), "failed to remove the symlink") {
    time.Sleep(100 * time.Millisecond)
    err = uninstall() // covers TOCTOU races
}

Prevention

When it happens

Trigger: Calling Uninstall or createOrUpdateLink when os.Remove fails on the symlink: directory lacks write/execute permission, immutable file attribute set (chattr +i), file locked by another process on Windows, or a TOCTOU race where the link was already removed.

Common situations: The plugins bin directory is owned by root after running the CLI with sudo once, so later non-root runs cannot delete links; or on Windows an antivirus/terminal holds a handle to the plugin binary.

Related errors


AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28). Data as JSON: /api/errors/b655f1136d3ac9dc. Report an issue: GitHub.