{"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":"exception","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/c9def3e214014c1188faabfc4a5bde5095139765/internal/getmodules/getter.go#L115-L151","documentation":"Returned by getWithGoGetter (getter.go:133) when, after successfully creating the destination directory for a cached-module reuse, copy.CopyDir(prevDir, instPath) fails. The reusingGetter copies the previously-fetched module tree rather than re-downloading; a copy failure means the cached source tree could not be reproduced at the destination.","triggerScenarios":"A module packageAddr was already fetched once (cache hit in reusingGetter), the mkdir succeeded, but copying the cached directory tree failed. The message reports prevDir, instPath, and the copy error.","commonSituations":"The previously-cached module directory (prevDir) was deleted or moved between the cache hit and the copy (race with cleanup). Disk full mid-copy. Permission mismatch where prevDir is readable but a sub-file is not. Filesystem errors on network-mounted volumes. Concurrent runs mutating the cache.","solutions":["Read the copy error in the message: 'no such file' → the cached prevDir was removed; 'permission denied' → fix read perms on prevDir; 'no space' → free disk.","Run terraform init -upgrade to discard the stale/partial cache and re-download fresh.","Remove the .terraform/modules cache directory and re-run init so the source tree is re-fetched instead of copied.","Serialize parallel terraform runs sharing the same cache to avoid races."],"exampleFix":"# before — cache hit but prevDir was deleted by a parallel run\n\n# after — clear cache and re-fetch\nrm -rf .terraform/modules\nterraform init","handlingStrategy":"retry","validationCode":"// Confirm the cached source tree still exists before reuse\nfunc cacheIntact(prevDir string) bool {\n    info, err := os.Stat(prevDir)\n    return err == nil && info.IsDir()\n}","typeGuard":"func cacheIntact(prevDir string) bool {\n    info, err := os.Stat(prevDir)\n    return err == nil && info.IsDir()\n}","tryCatchPattern":"if err := getter.Get(ctx, ...); err != nil {\n    if strings.Contains(err.Error(), \"failed to copy from\") {\n        // cache likely stale — clear and re-fetch fresh\n        os.RemoveAll(filepath.Dir(prevDir))\n        err = getter.Get(ctx, ...)\n    }\n    return err\n}","preventionTips":["Avoid concurrent processes that delete from .terraform/modules while init runs.","Use init -upgrade when copy failures appear (forces a fresh download).","Run init in a clean, writable workspace in CI."],"tags":["getmodules","go-getter","filesystem","cache","modules"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}