hashicorp/terraform · error

error loading plugin path

Error message

error loading plugin path: %s

What it means

Thrown by state_show.go when c.loadPluginPath() returns an error. loadPluginPath reads the user-supplied plugin override path (typically from terraform config's `plugin_directory` or the `terraform -plugin-dir` flag) and validates it. The wrapped error is flattened with %s.

Solutions

  1. Check ~/.terraformrc (or TF_CLI_CONFIG_FILE) for the `plugin_directory` entry and verify the path exists.
  2. Drop the `-plugin-dir` flag if you want Terraform to use the normal registry install path.
  3. Run `terraform init` to (re)populate the plugin cache.
  4. Fix filesystem permissions on the configured plugin directory.

Example fix

# before
 cat ~/.terraformrc
 plugin_directory = "/opt/terraform-plugins"

# after
 mkdir -p /opt/terraform-plugins
 terraform providers lock
 terraform state show aws_instance.web
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check plugin_directory before invoking state show.
if c.pluginPath != "" {
    if info, err := os.Stat(c.pluginPath); err != nil || !info.IsDir() {
        return fmt.Errorf("plugin_directory %s invalid: %w", c.pluginPath, err)
    }
}

Try / catch

if c.pluginPath, err = c.loadPluginPath(); err != nil {
    diags = diags.Append(fmt.Errorf("error loading plugin path: %s; remove plugin_directory from CLI config or fix path", err))
    view.Diagnostics(diags)
    return 1
}

Prevention

When it happens

Trigger: A plugin_directory is configured in the CLI config or passed via -plugin-dir, but the path does not exist, is not a directory, is unreadable, or contains invalid entries when Terraform validates it.

Common situations: Stale `plugin_directory` in ~/.terraformrc pointing at a removed dir; `-plugin-dir=...` typo; vendored plugin directory was deleted by a clean step; permissions on the plugin cache dir prevent reading.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/428b506e02f7a96c. Report an issue: GitHub.

Appendix: source

Thrown at internal/command/state_show.go:49

	// Parse and apply global view arguments
	common, args := arguments.ParseView(args)
	c.View.Configure(common)

	parsedArgs, diags := arguments.ParseStateShow(args)
	if diags.HasErrors() {
		c.View.Diagnostics(diags)
		c.View.HelpPrompt("state show")
		return 1
	}

	c.Meta.statePath = parsedArgs.StatePath
	c.viewType = parsedArgs.ViewType
	view := views.NewShow(parsedArgs.ViewType, c.View)

	// Check for user-supplied plugin path
	var err error
	if c.pluginPath, err = c.loadPluginPath(); err != nil {
		diags = diags.Append(fmt.Errorf("error loading plugin path: %s", err))
		view.Diagnostics(diags)
		return 1
	}

	// Load the backend
	b, diags := c.backend(".", c.viewType)
	if diags.HasErrors() {
		return view.DisplayResourceInstanceState(jsonformat.State{}, diags)
	}

	// We require a local backend
	local, ok := b.(backendrun.Local)
	if !ok {
		diags = diags.Append(ErrUnsupportedLocalOp)
		return view.DisplayResourceInstanceState(jsonformat.State{}, diags)
	}

	// This is a read-only command

View on GitHub (pinned to d32a084675)