{"record":{"id":"9838f8777938fdbb","repo":"multica-ai/multica","slug":"create-temp-for-s-w","errorCode":null,"errorMessage":"create temp for %s: %w","messagePattern":"create temp for (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/internal/daemon/execenv/hermes_home.go","lineNumber":917,"sourceCode":"\n// marshalYAMLToFile renders a YAML node to dst as a 0600 file (it can hold\n// inline secrets) via atomic replace.\nfunc marshalYAMLToFile(doc *yaml.Node, dst string) error {\n\tout, err := yaml.Marshal(doc)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"marshal hermes config: %w\", err)\n\t}\n\treturn writeFileAtomic(dst, out, 0o600)\n}\n\n// writeFileAtomic writes data to a temp file in the destination directory with\n// the given perms, then renames it over dst — so readers never see a partial\n// file and a prior file's looser permissions are replaced.\nfunc writeFileAtomic(dst string, data []byte, perm os.FileMode) error {\n\tdir := filepath.Dir(dst)\n\ttmp, err := os.CreateTemp(dir, \".hermes-tmp-*\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"create temp for %s: %w\", dst, err)\n\t}\n\ttmpName := tmp.Name()\n\tdefer os.Remove(tmpName) // no-op once renamed\n\tif _, err := tmp.Write(data); err != nil {\n\t\ttmp.Close()\n\t\treturn fmt.Errorf(\"write temp for %s: %w\", dst, err)\n\t}\n\tif err := tmp.Chmod(perm); err != nil {\n\t\ttmp.Close()\n\t\treturn fmt.Errorf(\"chmod temp for %s: %w\", dst, err)\n\t}\n\tif err := tmp.Close(); err != nil {\n\t\treturn fmt.Errorf(\"close temp for %s: %w\", dst, err)\n\t}\n\tif err := os.Rename(tmpName, dst); err != nil {\n\t\treturn fmt.Errorf(\"rename temp to %s: %w\", dst, err)\n\t}\n\treturn nil","sourceCodeStart":899,"sourceCodeEnd":935,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/internal/daemon/execenv/hermes_home.go#L899-L935","documentation":"writeFileAtomic could not create a temp file in the destination directory (os.CreateTemp with prefix .hermes-tmp-*). Every derived-file write (config.yaml, marker, memory store sidecars) goes through this atomic-write helper; failure here usually means the destination directory is missing, unwritable, or the filesystem is exhausted.","triggerScenarios":"Destination dir was deleted concurrently; daemon lacks write permission on the overlay/config dir; ENOSPC (disk/quota full); EMFILE (too many open files); read-only filesystem.","commonSituations":"Disk-full CI boxes or containers where env RootDir lives on a small volume; overlay dirs wiped by GC mid-prepare; overlay on a read-only mount after a disk error; long-running daemon leaking file descriptors.","solutions":["Check df -h and quota on the filesystem holding the destination path; free space or raise the quota.","Verify the destination directory exists and is writable by the daemon user; recreate/fix as needed.","Check the daemon's open-FD count (`ls /proc/<pid>/fd | wc -l`) and restart it if leaking.","If the FS remounted read-only after an error, address the disk problem and remount."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if err := ensureWritableDir(filepath.Dir(dst)); err != nil {\n\treturn fmt.Errorf(\"cannot write to %s: %w\", filepath.Dir(dst), err)\n}\n\nfunc ensureWritableDir(dir string) error {\n\tfi, err := os.Stat(dir)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !fi.IsDir() {\n\t\treturn fmt.Errorf(\"not a directory: %s\", dir)\n\t}\n\tprobe, perr := os.CreateTemp(dir, \".probe-*\")\n\tif perr != nil {\n\t\treturn perr\n\t}\n\tprobe.Close()\n\tos.Remove(probe.Name())\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":"if err := writeFileAtomic(dst, data, 0o600); err != nil {\n\tvar pe *os.PathError\n\tif errors.As(err, &pe) && (errors.Is(pe.Err, syscall.ENOSPC) || errors.Is(pe.Err, syscall.EROFS)) {\n\t\tlog.Printf(\"storage problem on %s: %v — free space / check mount\", filepath.Dir(dst), pe.Err)\n\t}\n\treturn err\n}","preventionTips":["Alert on disk usage of the env/workspaces volume before it hits 100%.","Validate writability of destination dirs at daemon startup, not mid-task."],"tags":["filesystem","disk-full","atomic-write","hermes","execenv"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}