{"record":{"id":"94c48b0e6b86604e","repo":"hashicorp/terraform","slug":"failed-to-copy-from-s-to-s-s","errorCode":null,"errorMessage":"failed to copy from %s to %s: %s","messagePattern":"failed to copy from (.+?) to (.+?): (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/getmodules/getter.go","lineNumber":133,"sourceCode":"// the String method on a valid addrs.ModulePackage value.\n//\n// The errors returned by this function are those surfaced by the underlying\n// go-getter library, which have very inconsistent quality as\n// end-user-actionable error messages. At this time we do not have any\n// reasonable way to improve these error messages at this layer because\n// the underlying errors are not separately recognizable.\nfunc (g reusingGetter) getWithGoGetter(ctx context.Context, instPath, packageAddr string) error {\n\tvar err error\n\n\tif prevDir, exists := g[packageAddr]; exists {\n\t\tlog.Printf(\"[TRACE] getmodules: copying previous install of %q from %s to %s\", packageAddr, prevDir, instPath)\n\t\terr := os.Mkdir(instPath, os.ModePerm)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to create directory %s: %s\", instPath, err)\n\t\t}\n\t\terr = copy.CopyDir(instPath, prevDir)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to copy from %s to %s: %s\", prevDir, instPath, err)\n\t\t}\n\t} else {\n\t\tlog.Printf(\"[TRACE] getmodules: fetching %q to %q\", packageAddr, instPath)\n\t\tclient := getter.Client{\n\t\t\tSrc: packageAddr,\n\t\t\tDst: instPath,\n\t\t\tPwd: instPath,\n\n\t\t\tMode: getter.ClientModeDir,\n\n\t\t\tDetectors:     goGetterNoDetectors, // our caller should've already done detection\n\t\t\tDecompressors: goGetterDecompressors,\n\t\t\tGetters:       goGetterGetters,\n\t\t\tCtx:           ctx,\n\t\t}\n\t\terr = client.Get()\n\t\tif err != nil {\n\t\t\treturn err","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/getmodules/getter.go#L115-L151","documentation":"Thrown by reusingGetter.getWithGoGetter after the install target directory was created successfully but copy.CopyDir failed copying a previously-cached module install (prevDir) into the new install path (instPath). The first %s is the cache source dir, the second the new dest dir, the third the underlying copy error. It indicates a filesystem-level failure during the module-cache reuse optimization, not a network fetch problem.","triggerScenarios":"A second module call references the same packageAddr already downloaded earlier in the same run; the getter reuses it by copying prevDir -> instDir, but CopyDir returns an error (permissions, read-only source, dest on a full/read-only filesystem, or source dir vanished mid-copy).","commonSituations":"Module cache directory owned by root/another user while Terraform runs as non-root; NFS or mounted volume with permission restrictions; disk-full CI runner; antivirus/backup process locking files on Windows; cache dir manually deleted or rotated between detection and copy.","solutions":["Check read permission on the cached source dir and write permission on the install dir: ls -ld <prevDir> <instPath> and ensure the Terraform process owns or can write both.","Free disk space or raise inode quota on the filesystem holding the module install directory (often .terraform).","Clear the module cache / remove .terraform/modules and re-run terraform init so the package is fetched fresh instead of copied.","If on a network/mounted filesystem, verify it is mounted read-write and not saturated; rerun init after remounting.","On Windows, disable or except antivirus from scanning the cache dir, or close backup tools that lock files."],"exampleFix":"# before: cache dir owned by root, terraform runs as user -> copy fails\nsudo chown -R $(whoami) .terraform/modules\n\n# then re-run\nterraform init","handlingStrategy":"try-catch","validationCode":"// Before calling getWithGoGetter, verify prevDir readability and instPath writability:\n// import \"os\"\n// if fi, err := os.Stat(prevDir); err != nil || !fi.IsDir() {\n//     return fmt.Errorf(\"cache dir unavailable: %w\", err)\n// }\n// if err := os.MkdirAll(filepath.Dir(instPath), 0o755); err != nil {\n//     return err\n// }","typeGuard":null,"tryCatchPattern":"// Wrap the getter call; on copy failure, fall back to a fresh fetch by removing the cached prevDir entry and retrying once.\n// err := g.getWithGoGetter(ctx, instPath, addr)\n// if err != nil && strings.Contains(err.Error(), \"failed to copy from\") {\n//     delete(g, addr)            // invalidate stale cache entry\n//     err = g.getWithGoGetter(ctx, instPath, addr) // retry once with fresh fetch\n// }","preventionTips":["Run Terraform as the user that owns the .terraform/modules cache directory.","Keep module cache on a writable local filesystem, not a read-only mount.","Ensure adequate free disk/inodes on the working directory's volume before init.","Avoid deleting or chowning the cache directory mid-run."],"tags":["filesystem","module-installation","caching","copy"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}