{"record":{"id":"15162dc9f9b9a2ab","repo":"multica-ai/multica","slug":"write-temp-file-w","errorCode":null,"errorMessage":"write temp file: %w","messagePattern":"write temp file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/internal/cli/update.go","lineNumber":456,"sourceCode":"\t} else {\n\t\tbinaryData, err = extractBinaryFromTarGz(bytes.NewReader(archiveData), binaryName)\n\t}\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"extract binary: %w\", err)\n\t}\n\n\t// Atomic replace: write to temp file, then rename over the original.\n\tdir := filepath.Dir(exePath)\n\ttmpFile, err := os.CreateTemp(dir, \"multica-update-*\")\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"create temp file: %w\", err)\n\t}\n\ttmpPath := tmpFile.Name()\n\n\tif _, err := tmpFile.Write(binaryData); err != nil {\n\t\ttmpFile.Close()\n\t\tos.Remove(tmpPath)\n\t\treturn \"\", fmt.Errorf(\"write temp file: %w\", err)\n\t}\n\ttmpFile.Close()\n\n\t// Preserve original file permissions.\n\tinfo, err := os.Stat(exePath)\n\tif err != nil {\n\t\tos.Remove(tmpPath)\n\t\treturn \"\", fmt.Errorf(\"stat original binary: %w\", err)\n\t}\n\tif err := os.Chmod(tmpPath, info.Mode()); err != nil {\n\t\tos.Remove(tmpPath)\n\t\treturn \"\", fmt.Errorf(\"chmod temp file: %w\", err)\n\t}\n\n\t// Replace the original binary. On Windows this moves the running executable\n\t// aside first; on Unix a plain rename over the running inode is fine.\n\tif err := replaceBinary(tmpPath, exePath); err != nil {\n\t\tos.Remove(tmpPath)","sourceCodeStart":438,"sourceCodeEnd":474,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/internal/cli/update.go#L438-L474","documentation":"Writing the extracted binary into the just-created temp file failed, wrapped as 'write temp file: %w'; the temp file is closed and removed before returning. The binary (~tens of MB) must fully land on disk before the rename, so ENOSPC (disk full), EDQUOT (quota), or an I/O error on a failing device surfaces here.","triggerScenarios":"Disk filled between CreateTemp and Write; per-user quota exceeded; the filesystem degraded (NFS/overlayfs write errors, SD-card failure); antivirus/EDR on Windows locking the temp file mid-write.","commonSituations":"Small VM disks; overlay2 containers with a full upper layer; the update firing right as a log file fills the last space.","solutions":["Free space on the filesystem holding the binary directory and retry (df <dir>).","Raise the user's quota if EDQUOT.","Exclude the binary directory from aggressive AV scanning on Windows.","On storage I/O errors, remount/replace the failing disk — repeated write failures are hardware symptoms."],"exampleFix":"null","handlingStrategy":"retry","validationCode":"var stat syscall.Statfs_t\nif err := syscall.Statfs(filepath.Dir(exePath), &stat); err == nil {\n    free := stat.Bavail * uint64(stat.Bsize)\n    if free < uint64(len(binaryData))+1<<20 { // payload + 1MB headroom\n        // not enough space: clean up before updating\n    }\n}","typeGuard":null,"tryCatchPattern":"out, err := cli.UpdateViaDownload(ver)\nif err != nil {\n    var pe *fs.PathError\n    if errors.As(err, &pe) && errors.Is(pe.Err, syscall.ENOSPC) {\n        // free space and retry; the temp file was already cleaned up by the updater\n    }\n}","preventionTips":["Monitor disk usage and alert before it hits zero","Clean old logs/artifacts before running updates","Retry the update after freeing space — the failure cleans up after itself"],"tags":["filesystem","disk-full","io","temp-file"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}