hashicorp/terraform · error
failed to read stacks plugin stored path file
Error message
failed to read stacks plugin stored path file: %w
What it means
Thrown inside the stacks plugin path loader when os.ReadFile(cacheStorePath) fails for the .stackspluginpath file. Note the asymmetry: os.Stat already succeeded (we are in the else branch), so this only fires for a narrow window — file deleted between stat and read, permission denied on read, or an I/O error. The path comes from c.WorkingDir.DataDir() joined with `.stackspluginpath`.
Solutions
- Re-run `terraform init` to regenerate `.stackspluginpath` and the plugin cache.
- Check permissions on the data dir and `.stackspluginpath`: `ls -la .terraform/`.
- Avoid running multiple terraform commands concurrently in the same working directory.
- Delete `.stackspluginpath` and let Terraform fall back to the default plugin path on next run.
Example fix
# before: stale .stackspluginpath rm -f .terraform/.stackspluginpath terraform stacks <args> # after (regenerated) terraform init terraform stacks <args>
Defensive patterns
Strategy: validation
Validate before calling
// Before reading .stackspluginpath, ensure exclusive access.
f, err := os.OpenFile(cacheStorePath, os.O_RDWR, 0)
if err != nil {
return "", nil // fall through to default path
}
defer f.Close()
if err := flock.Try(f.Fd()); err != nil {
return "", fmt.Errorf("another terraform process holds .stackspluginpath: %w", err)
} Try / catch
data, err := os.ReadFile(cacheStorePath)
if err != nil {
if os.IsNotExist(err) {
return defaultPluginPath, nil // file gone; use default
}
// transient: stat said it existed, read failed — log and fall back
log.Printf("[WARN] .stackspluginpath read failed (%v); using default %s", err, defaultPluginPath)
return defaultPluginPath, nil
} Prevention
- Never run multiple `terraform stacks` / `terraform init` concurrently in one working dir.
- Use TF_DATA_DIR per concurrent pipeline job to isolate the cache.
- Pin ownership of `.terraform/` to the runtime uid in containers.
- Add `.stackspluginpath` to a clean checkout step rather than relying on stat/read races.
When it happens
Trigger: Another process deletes `.stackspluginpath` between the os.Stat and os.ReadFile calls; file mode denies read to the current user (chmod 000); filesystem I/O error (NFS hiccup, disk failure); symlink loop or dangling symlink that stat followed but read cannot.
Common situations: Concurrent `terraform init` and `terraform stacks` runs racing on the same data dir; permissions altered by a CI step between runs; mounted volume with intermittent I/O errors; `.terraform` dir restored from a tarball that lost ownership.
Related errors
- failed to create stacks plugin stored path file
- failed to initialize stacksplugin cache directory
- error loading plugin path
- error loading plugin path
- Failed to read file
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/d4e50ed1e5e41c1e.
Report an issue: GitHub.
Appendix: source
Thrown at internal/command/stacks.go:394
func (c *StacksCommand) initPackagesCache() (string, error) {
var pluginPath string
defaultPluginPath := path.Join(c.CLIConfigDir, StacksPluginDataDir)
cacheStorePath := path.Join(c.WorkingDir.DataDir(), ".stackspluginpath")
if _, err := os.Stat(cacheStorePath); err != nil {
if os.IsNotExist(err) {
log.Printf("[TRACE] No stacksplugin cache path store at '%s`, using default '%s'", cacheStorePath, defaultPluginPath)
// Use the default plugin cache path if the file does not exist
pluginPath = defaultPluginPath
} else {
log.Printf("[TRACE] Failed to check the stacksplugin cache path store at '%s', using default '%s'", cacheStorePath, defaultPluginPath)
// Use the default plugin cache path if there was an error checking the file
pluginPath = defaultPluginPath
}
} else {
data, err := os.ReadFile(cacheStorePath)
if err != nil {
return "", fmt.Errorf("failed to read stacks plugin stored path file: %w", err)
}
pluginPath = string(data)
}
if info, err := os.Stat(pluginPath); err != nil || !info.IsDir() {
log.Printf("[TRACE] initialized stacksplugin cache directory at %q", pluginPath)
err = os.MkdirAll(pluginPath, 0755)
if err != nil {
return "", fmt.Errorf("failed to initialize stacksplugin cache directory: %w", err)
}
} else {
log.Printf("[TRACE] stacksplugin cache directory found at %q", pluginPath)
}
return pluginPath, nil
}
func (c *StacksCommand) storeStacksPluginPath(pluginCachePath string) error {View on GitHub (pinned to d32a084675)