hasura/graphql-engine · error

failed to read the symlink in %q: %w

Error message

failed to read the symlink in %q: %w

What it means

Thrown when os.Lstat fails for a path that should be a plugin symlink during uninstall/relink, and the error is anything other than 'file does not exist' (which is treated as success). The wrapped error typically indicates permission problems on the parent directory or an I/O failure reading the file's metadata.

Source

Thrown at cli/plugins/util.go:236

			return errors.E(
				op,
				fmt.Errorf("failed to create a symlink from %q to %q: %w", binary, dst, err),
			)
		}
	}

	return nil
}

// 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, "-", "_")

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Check permissions on the full path: namei -l ~/.hasura/plugins/bin/<plugin> and fix with chmod/chown.
  2. Verify no path component is a file rather than a directory; recreate the bin directory if corrupted.
  3. Temporarily disable antivirus/lockers on Windows and retry uninstall.
  4. As a last resort, manually delete the plugins bin directory and let the CLI recreate it.
Defensive patterns

Strategy: validation

Validate before calling

// verify the path is statable before uninstalling
if _, err := os.Lstat(linkPath); err != nil && !errors.Is(err, fs.ErrNotExist) {
    log.Fatalf("cannot stat %s: %v", linkPath, err)
}

Try / catch

if err := plugins.Uninstall(...); err != nil {
    if strings.Contains(err.Error(), "failed to read the symlink") {
        // directory-level permission problem; fix and retry
    }
}

Prevention

When it happens

Trigger: Calling Uninstall or createOrUpdateLink when os.Lstat on the symlink path returns a non-ErrNotExist error: permission denied on the containing directory, a path component that is not a directory, or a filesystem/IO error.

Common situations: The plugins bin directory or an ancestor was made read-only, the directory was replaced by a Docker bind mount with odd permissions, or an antivirus/locking mechanism on Windows interferes with stat calls.

Related errors


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