hashicorp/terraform · error
failed to initialize cloudplugin cache directory
Error message
failed to initialize cloudplugin cache directory: %w
What it means
Thrown by CloudCommand.initPackagesCache when os.MkdirAll fails to create the cloudplugin cache directory (path.Join(WorkingDir.DataDir(), CloudPluginDataDir)). Terraform caches the cloudplugin binary there; if it cannot create the directory, the cloud subcommand cannot run.
Solutions
- Verify the data dir resolves correctly and is writable: `terraform -version` then check `echo $TF_DATA_DIR` / `$HOME`.
- Create and chmod the parent: `mkdir -p $HOME/.terraform.d && chmod u+w $HOME/.terraform.d`.
- Unset or fix TF_DATA_DIR if it points somewhere inappropriate.
- For containers, ensure HOME is set to a writable path and a writable volume is mounted there.
Example fix
// before: TF_DATA_DIR=/readonly-cache // $ unset TF_DATA_DIR // $ mkdir -p $HOME/.terraform.d && chmod 755 $HOME/.terraform.d // after: terraform cloud / cloudplugin cache initializes successfully
Defensive patterns
Strategy: validation
Validate before calling
func dataDirWritable(dataDir string) error {
if dataDir == "" { dataDir = filepath.Join(os.Getenv("HOME"), ".terraform.d") }
if err := os.MkdirAll(dataDir, 0755); err != nil {
return fmt.Errorf("cannot use data dir %s: %w", dataDir, err)
}
probe, err := os.CreateTemp(dataDir, ".perm-*")
if err != nil { return err }
probe.Close(); os.Remove(probe.Name())
return nil
} Prevention
- Set HOME (and optionally TF_DATA_DIR) to a writable path in CI/containers.
- Mount a writable volume at $HOME.
- Validate the data dir is writable before running `terraform cloud` flows.
When it happens
Trigger: The data directory (~/.terraform.d or $TF_DATA_DIR) or the cloudplugin subdirectory cannot be created — read-only filesystem, permission denied, or an invalid/empty path returned by WorkingDir.DataDir().
Common situations: TF_DATA_DIR points at a read-only or non-writable location; HOME unset in a container/service; running in a sandbox with no home write access; a parent path component is a file not a directory.
Related errors
- cannot read
- Can't ask approval for state migration when interactive…
- can't show a saved cloud plan unless the current root…
- cannot create temporary file to update credentials
- Cannot read directory
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/6dd0f416e05fe9f1.
Report an issue: GitHub.
Appendix: source
Thrown at internal/command/cloud.go:256
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Warning,
"Cloud plugin development overrides are in effect",
detailMsg,
))
}
log.Printf("[TRACE] plugin %q binary located at %q%s", version.ProductVersion, version.Path, cacheTraceMsg)
c.pluginBinary = version.Path
return diags
}
func (c *CloudCommand) initPackagesCache() (string, error) {
packagesPath := path.Join(c.WorkingDir.DataDir(), CloudPluginDataDir)
if info, err := os.Stat(packagesPath); err != nil || !info.IsDir() {
log.Printf("[TRACE] initialized cloudplugin cache directory at %q", packagesPath)
err = os.MkdirAll(packagesPath, 0755)
if err != nil {
return "", fmt.Errorf("failed to initialize cloudplugin cache directory: %w", err)
}
} else {
log.Printf("[TRACE] cloudplugin cache directory found at %q", packagesPath)
}
return packagesPath, nil
}
// Run runs the cloud command with the given arguments.
func (c *CloudCommand) Run(args []string) int {
args = c.Meta.process(args)
return c.realRun(args, c.Meta.Streams.Stdout.File, c.Meta.Streams.Stderr.File)
}
// Help returns help text for the cloud command.
func (c *CloudCommand) Help() string {
helpText := new(bytes.Buffer)
if exitCode := c.realRun([]string{}, helpText, io.Discard); exitCode != 0 {View on GitHub (pinned to d32a084675)