{"record":{"id":"05e1d70fcbcc9da2","repo":"kubernetes/kops","slug":"error-renaming-extracted-temp-dir-s-s-v","errorCode":null,"errorMessage":"error renaming extracted temp dir %s -> %s: %v","messagePattern":"error renaming extracted temp dir (.+?) -> (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/assetstore.go","lineNumber":319,"sourceCode":"\tif _, err := os.Stat(extracted); os.IsNotExist(err) {\n\t\t// We extract to a temporary dir which we then rename so this is atomic\n\t\t// (untarring can be slow, and we might crash / be interrupted half-way through)\n\t\textractedTemp := extracted + \".tmp-\" + strconv.FormatInt(time.Now().UnixNano(), 10)\n\t\terr := os.MkdirAll(extractedTemp, 0o755)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error creating directories %q: %v\", path.Dir(extractedTemp), err)\n\t\t}\n\n\t\targs := []string{\"tar\", \"zxf\", archiveFile, \"-C\", extractedTemp}\n\t\tklog.Infof(\"running extract command %s\", args)\n\t\tcmd := exec.Command(args[0], args[1:]...)\n\t\toutput, err := cmd.CombinedOutput()\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error expanding asset file %q %v: %s\", archiveFile, err, string(output))\n\t\t}\n\n\t\tif err := os.Rename(extractedTemp, extracted); err != nil {\n\t\t\treturn fmt.Errorf(\"error renaming extracted temp dir %s -> %s: %v\", extractedTemp, extracted, err)\n\t\t}\n\t}\n\n\tlocalBase := extracted\n\tassetBase := \"\"\n\n\twalker := func(localPath string, info os.FileInfo, err error) error {\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error descending into path %q: %v\", localPath, err)\n\t\t}\n\n\t\tif info.IsDir() {\n\t\t\treturn nil\n\t\t}\n\n\t\trelativePath, err := filepath.Rel(localBase, localPath)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error finding relative path for %q: %v\", localPath, err)","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/assetstore.go#L301-L337","documentation":"Extraction is made atomic by extracting to a temp dir then os.Rename(extractedTemp, extracted). If the rename fails — most commonly because the target path already exists or spans filesystems — addArchive returns 'error renaming extracted temp dir %s -> %s: %v'.","triggerScenarios":"addURLs -> addArchive where tar succeeded but os.Rename to the final extracted path fails: target dir created concurrently by another process, EXDEV (temp and target on different mounts), or EACCES on the parent.","commonSituations":"Concurrent kOps runs racing to extract the same asset (another process already renamed/created the target); extraction dir configured on a different mount from the working dir; leftover directory from a previously interrupted run.","solutions":["Check the wrapped %v for EEXIST: if the target now exists, the asset is already extracted and the operation can be retried/skipped.","Remove a stale half-populated directory at the extraction path and retry.","Ensure the asset store working dir and extraction target are on the same filesystem to avoid EXDEV.","Avoid concurrent kOps processes sharing one asset store working directory.","Fix parent directory write permissions if EACCES."],"exampleFix":"// handle the already-extracted race\nif err := os.Rename(extractedTemp, extracted); err != nil {\n  if os.IsExist(err) {\n    os.RemoveAll(extractedTemp) // someone else won the race; target already present\n    return nil\n  }\n  return fmt.Errorf(\"error renaming extracted temp dir %s -> %s: %v\", extractedTemp, extracted, err)\n}","handlingStrategy":"retry","validationCode":"import fs from \"fs\" // same-filesystem check before extraction\nconst st = fs.statSync(workDir)\nif (st.dev !== fs.statSync(require(\"path\").dirname(extracted)).dev) throw new Error(\"EXDEV risk: extraction target on different mount\")","typeGuard":"function isEXDEV(err: NodeJS.ErrnoException): boolean { return err.code === \"EXDEV\" }\nfunction isEEXIST(err: NodeJS.ErrnoException): boolean { return err.code === \"EEXIST\" }","tryCatchPattern":"try {\n  await addURLs(urls)\n} catch (e) {\n  if (/error renaming extracted temp dir/.test(e.message)) {\n    // EEXIST => asset already extracted by a racing run: safe to proceed\n    // otherwise: clear stale dir and retry once\n  }\n  throw e\n}","preventionTips":["Never run multiple kOps processes against the same asset store working dir.","Keep working dir and extraction target on the same filesystem.","Clean up leftover directories from interrupted runs.","Check parent dir permissions before extraction."],"tags":["filesystem","rename","assets"],"backgroundTag":"rename-failed","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}