{"record":{"id":"18bfe1487ff25327","repo":"dagger/dagger","slug":"write-resolv-conf-w","errorCode":null,"errorMessage":"write resolv.conf: %w","messagePattern":"write resolv\\.conf: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/engineutil/executor_spec.go","lineNumber":252,"sourceCode":"\t\treturn fmt.Errorf(\"create container resolv.conf tmp file: %w\", err)\n\t}\n\tdefer ctrResolvFile.Close()\n\tstate.resolvConfPath = ctrResolvFile.Name()\n\tstate.cleanups.Add(\"remove resolv.conf\", func() error {\n\t\treturn os.RemoveAll(state.resolvConfPath)\n\t})\n\n\tif err := ctrResolvFile.Chmod(baseResolvStat.Mode().Perm()); err != nil {\n\t\treturn fmt.Errorf(\"chmod resolv.conf: %w\", err)\n\t}\n\n\tscanner := bufio.NewScanner(baseResolvFile)\n\tvar replaced bool\n\tfor scanner.Scan() {\n\t\tline := scanner.Text()\n\t\tif !strings.HasPrefix(line, \"search\") {\n\t\t\tif _, err := fmt.Fprintln(ctrResolvFile, line); err != nil {\n\t\t\t\treturn fmt.Errorf(\"write resolv.conf: %w\", err)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\tdomains := strings.Fields(line)[1:]\n\t\tdomains = append(domains, extraSearchDomains...)\n\t\tif _, err := fmt.Fprintln(ctrResolvFile, \"search\", strings.Join(domains, \" \")); err != nil {\n\t\t\treturn fmt.Errorf(\"write resolv.conf: %w\", err)\n\t\t}\n\t\treplaced = true\n\t}\n\tif err := scanner.Err(); err != nil {\n\t\treturn fmt.Errorf(\"read resolv.conf: %w\", err)\n\t}\n\tif !replaced {\n\t\tif _, err := fmt.Fprintln(ctrResolvFile, \"search\", strings.Join(extraSearchDomains, \" \")); err != nil {\n\t\t\treturn fmt.Errorf(\"write resolv.conf: %w\", err)\n\t\t}","sourceCodeStart":234,"sourceCodeEnd":270,"githubUrl":"https://github.com/dagger/dagger/blob/82ba2681dbe30d3547a1dc50ea495900ab5b6047/engine/engineutil/executor_spec.go#L234-L270","documentation":"setupNetwork copies the base resolv.conf line-by-line into the container's temp file, skipping 'search' lines so it can rewrite them. This error wraps a write failure from fmt.Fprintln on the temp file while writing a non-search line. It indicates the container's resolv.conf could not be fully populated.","triggerScenarios":"Write to the just-created temp resolv.conf fails — typically disk full, the temp file was removed mid-write, or the fd was closed early.","commonSituations":"Node disk full; aggressive tmp cleaners racing with setup; I/O errors on the temp filesystem (EIO on faulty disks or full overlay).","solutions":["Check free space on the filesystem backing TMPDIR (df -h) and free it if full.","Re-run; if transient EIO, check node disk health (dmesg for I/O errors).","Ensure no cleanup job deletes /tmp entries during engine startup.","Inspect the wrapped cause with errors.Is/As to distinguish ENOSPC from other I/O failures."],"exampleFix":"// before: node disk 100% full\n$ df -h /tmp  # 0 available\n// after: free space or relocate temp dir\nTMPDIR=/var/tmp dagger ...","handlingStrategy":"retry","validationCode":"// check free space on the temp filesystem before engine start\nif st, err := os.Statvfs == nil; true {\n}\n// simpler: shell precheck\ndf -h \"$TMPDIR\" || true\n// Go: use golang.org/x/sys/unix.Statfs and fail early if free < headroom","typeGuard":null,"tryCatchPattern":"if err != nil {\n\tif errors.Is(err, syscall.ENOSPC) {\n\t\t// free space / relocate TMPDIR, then retry setupNetwork\n\t}\n\treturn fmt.Errorf(\"resolv.conf write: %w\", err)\n}","preventionTips":["Alert on temp-volume disk usage (e.g. >85%) before ENOSPC hits.","Don't schedule /tmp cleanup jobs concurrently with engine startup.","Check node dmesg for I/O errors when writes fail intermittently."],"tags":["filesystem","resolv-conf","write-failed","io"],"backgroundTag":"file-write-failed","analyzedSha":"82ba2681dbe30d3547a1dc50ea495900ab5b6047","analyzedAt":"2026-09-05T07:21:37.930Z","contentChangedAt":"2026-09-05T07:21:37.930Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}