hashicorp/terraform · error

Error saving -plugin-dir to workspace directory

Error message

Error saving -plugin-dir to workspace directory: %s

What it means

Thrown by init_run.go when c.storePluginPath(c.pluginPath) fails while persisting the -plugin-dir flags to the workspace's .terraformrc/plugin-paths file. The %s is the underlying error.

Solutions

  1. Verify write permissions on the working directory and .terraform/: `ls -ld . .terraform`.
  2. Free disk space if the volume is full.
  3. Ensure the working directory is writable; avoid running init inside a read-only mount.

Example fix

$ chmod u+w . && terraform init -plugin-dir=/opt/plugins
Defensive patterns

Strategy: validation

Validate before calling

// Verify the workspace dir is writable before init with -plugin-dir.
func writableDir(p string) bool {
    return os.WriteFile(filepath.Join(p, ".w"), []byte("x"), 0644) == nil
}

Prevention

When it happens

Trigger: Running `terraform init -plugin-dir=...` (or with TF_PLUGIN_PATHS) when the workspace directory is read-only, full, or the plugin-paths metadata file cannot be written.

Common situations: Read-only checkout in CI; full disk; permissions on the .terraform directory; running init against a module path the user cannot write to.

Related errors


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

Appendix: source

Thrown at internal/command/init_run.go:55

	c.Meta.input = initArgs.InputEnabled
	c.Meta.targetFlags = initArgs.TargetFlags
	c.Meta.compactWarnings = initArgs.CompactWarnings

	// Copying the state only happens during backend migration, so setting
	// -force-copy implies -migrate-state
	if c.forceInitCopy {
		c.migrateState = true
	}

	if len(initArgs.PluginPath) > 0 {
		c.pluginPath = initArgs.PluginPath
	}

	// Get the working directory
	path := c.Meta.WorkingDir.RootModuleDir()

	if err := c.storePluginPath(c.pluginPath); err != nil {
		diags = diags.Append(fmt.Errorf("Error saving -plugin-dir to workspace directory: %s", err))
		view.Diagnostics(diags)
		return 1
	}

	// Initialization can be aborted by interruption signals
	ctx, done := c.InterruptibleContext(c.CommandContext())
	defer done()

	if initArgs.FromModule != "" {
		src := initArgs.FromModule

		empty, err := configs.IsEmptyDir(path, initArgs.TestsDirectory)
		if err != nil {
			diags = diags.Append(fmt.Errorf("Error validating destination directory: %s", err))
			view.Diagnostics(diags)
			return 1
		}
		if !empty {

View on GitHub (pinned to d32a084675)