{"record":{"id":"686d93ab084647c7","repo":"dagger/dagger","slug":"failed-to-rewrite-file-metadata-w","errorCode":null,"errorMessage":"failed to rewrite file metadata: %w","messagePattern":"failed to rewrite file metadata: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/filesync/localfs.go","lineNumber":1027,"sourceCode":"\t\t\treturn nil, err\n\t\t}\n\t\tdefer f.Close()\n\n\t\th := newHashFromStat(upperStat)\n\n\t\tcopyBuf := copyBufferPool.Get().(*[]byte)\n\t\twritten, err := io.CopyBuffer(io.MultiWriter(f, h), reader, *copyBuf)\n\t\twrittenBytes = written\n\t\tcopyBufferPool.Put(copyBuf)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to copy contents: %w\", err)\n\t\t}\n\t\tif err := f.Close(); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to close file: %w\", err)\n\t\t}\n\n\t\tif err := rewriteMetadata(fullPath, upperStat); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to rewrite file metadata: %w\", err)\n\t\t}\n\n\t\t// store the hash in an xattr so GetPreviousChange above can use that instead of re-hashing the file\n\t\tdgst := digest.NewDigest(hashutil.XXH3, h)\n\t\tif err := sysx.Setxattr(fullPath, hashXattrKey, []byte(dgst.String()), 0); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to set content hash xattr: %w\", err)\n\t\t}\n\n\t\treturn &ChangeWithStat{\n\t\t\tkind: expectedChangeKind,\n\t\t\tstat: &HashedStatInfo{\n\t\t\t\tStatInfo: StatInfo{upperStat},\n\t\t\t\tdgst:     dgst,\n\t\t\t},\n\t\t}, nil\n\t})\n\tif err != nil {\n\t\treturn nil, 0, err","sourceCodeStart":1009,"sourceCodeEnd":1045,"githubUrl":"https://github.com/dagger/dagger/blob/82ba2681dbe30d3547a1dc50ea495900ab5b6047/engine/filesync/localfs.go#L1009-L1045","documentation":"Wrapped by localFS.WriteFile when rewriteMetadata(fullPath, upperStat) fails after the file was successfully written and closed. rewriteMetadata restores the upstream file's ownership (Lchown), permission mode (Chmod), and timestamps (utimes). The file content is correct, but its metadata could not be applied, so the sync is aborted to avoid leaving an inconsistent copy.","triggerScenarios":"rewriteMetadata returns an error during WriteFile — most commonly Lchown failing because the process lacks privileges to set the target uid/gid, Chmod failing on the target filesystem, or utimes failing on a filesystem that doesn't support setting timestamps.","commonSituations":"Running the dagger engine/CLI as a non-root user while syncing files owned by other uids/gids (common in containerized or rootless setups); syncing onto a filesystem that ignores or rejects chown (some NFS mounts, FAT/exFAT, bind mounts with userns remapping); SELinux/AppArmor restrictions denying chown or chmod.","solutions":["Run the operation with sufficient privileges (root or a user that owns the target uid/gid), or in a rootless setup ensure user namespace mapping permits the chown","Check that the destination filesystem supports ownership/permission/timestamp changes (avoid FAT/exFAT destinations, check mount options like nosuid/user mapping)","Inspect the wrapped errno in the error message (%w chain) to identify which of chown/chmod/utimes failed and address that specific syscall restriction","If security modules (SELinux/AppArmor) deny the operation, adjust the policy or run outside the restricted context"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// pre-flight: can we chown/chmod/utimes on this target?\nprobe := filepath.Join(destDir, \".meta-probe\")\nos.WriteFile(probe, []byte(\"x\"), 0o600)\ndefer os.Remove(probe)\nif err := os.Chown(probe, os.Getuid(), os.Getgid()); err != nil {\n\treturn fmt.Errorf(\"target fs rejects chown: %w\", err)\n}\nif err := os.Chtimes(probe, time.Now(), time.Now()); err != nil {\n\treturn fmt.Errorf(\"target fs rejects utimes: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"err := rewriteMetadata(fullPath, upperStat)\nif err != nil {\n\tvar pathErr *os.PathError\n\tif errors.As(err, &pathErr) && errors.Is(pathErr.Err, syscall.EPERM) {\n\t\t// run privileged or adjust userns mapping, then retry\n\t}\n\treturn fmt.Errorf(\"metadata restore failed: %w\", err)\n}","preventionTips":["Run dagger with privileges adequate for the ownership of the files being synced, or use rootless mode with correct subuid/subgid mappings","Choose destination filesystems that support full POSIX metadata (ext4/xfs/btrfs/apfs), not FAT/exFAT","Keep source file ownership within the user/namespace range available to the engine","Test the sync target with a probe file that exercises chown/chmod/utimes before large operations"],"tags":["filesystem","permissions","filesync"],"backgroundTag":"chown-permission-denied","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"}