Repository navigation
Conversation
… set Destination filesystems that reject safetensors allocation calls can opt in with safetensors_staging_dir. The default remains a direct write. Co-authored-by: Cursor <cursoragent@cursor.com>
tongyx361
requested review from
PeterSH6,
eric-haibin-lin and
vermouth1992
as code owners
September 22, 2026 11:31
6 of 8 tasks
Users need to know the direct write fails on some shared, network, and mounted filesystems that reject safetensors allocation calls. Co-authored-by: Cursor <cursoragent@cursor.com>
Staging is for destinations that reject safetensors >= 0.8 serialize_file, such as HDFS FUSE set_len. Mounts that cannot rename at all are outside the final os.replace. Co-authored-by: Cursor <cursoragent@cursor.com>
The filesystem cases stay on McoreCheckpointConfig.safetensors_staging_dir. Actor and critic yaml comments and the save helpers link there. Co-authored-by: Cursor <cursoragent@cursor.com>
Collaborator
Author
|
Closing this. Pinning safetensors to 0.7 avoids the failure this staging path was written for, so the workaround does not need to land in verl.
pip install 'safetensors==0.7.*'The proper fix is still on the safetensors side (make |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Megatron HF safetensors saves write each shard directly on the destination filesystem. safetensors >= 0.8
serialize_file(safetensors#764) preallocates withFile::set_lenand thenrename/chmods a sibling temp file. HDFS FUSE returns ENOSYS fromset_len(safetensors#787). mountpoint-s3 fails thatrename/chmodwith ENOSYS or EPERM (safetensors#792). This PR adds an opt-in local POSIX staging directory soserialize_fileruns on local storage and the finished shard is copied onto the destination withos.replace. That final replace still requires a same-directory rename, so a mount that rejectsrenameentirely, including mountpoint-s3, is not a supported destination.nullor a blank path keeps the direct write. Ordinary local disks stay on that default. Any non-empty path enables staging; the installed safetensors version is not consulted.This is one independent slice of #7570. That combined PR is being closed in favor of this change plus the separate rollout PRs.
Checklist Before Starting
[{modules}] {type}: {description}.Duplicate-work check: open staging PRs such as #7869 (delta staging lifecycle), #4770 (PEFT key normalization), and #7286 (FSDP
map_location) do not addsafetensors_staging_dir. #7570 is the combined predecessor this slice is split out of, and it is being closed rather than left open beside this PR.Test
2 passed (6.62s) on Python 3.12 with the local Megatron and safetensors stack. The blank-dir case writes the destination path in place. The set-dir case serializes under the staging directory.
All 14 configured hooks passed, including
autogen-trainer-cfg.scripts/generate_trainer_config.shreports the generated Megatron trainer yaml is current.GPU saves onto HDFS FUSE, where safetensors >= 0.8
File::set_lenreturns ENOSYS, were not run. CPU tests do not establish that save.API and Usage Example
actor_rollout_ref.actor.checkpoint.safetensors_staging_dir=/scratch/hf # or critic.checkpoint.safetensors_staging_dir=/scratch/hfSet this only when the checkpoint directory cannot finish safetensors >= 0.8
serialize_file, and point it at a local POSIX directory on the same node. HDFS FUSE is the known case:File::set_lenreturns ENOSYS (safetensors#787). Leave the valuenullon ordinary local disks. Any non-empty path enables staging. The installed safetensors version is not consulted. safetensors#792 is the same 0.8 writer failing on mountpoint-s3rename/chmod; that mount also rejects the same-directoryos.replaceused to publish the copied shard, so it is not a supported destination.Design & Code Changes
serialize_file(safetensors#764): HDFS FUSE returns ENOSYS fromFile::set_len(safetensors#787). A mount that cannotrenameat all, such as mountpoint-s3 (safetensors#792), is outside this workaround because the copy still usesos.replace. This does not replacembridge_config.distributed_filesystem.McoreCheckpointConfig.safetensors_staging_dirdefaults tonulland is exposed on the Megatron actor and critic checkpoint configs. The generated Megatron trainer yaml is updated to match._stage_safetensors_writespatchessafetensors.torch.serialize_filefor the duration of_save_model_as_hf_via_bridge. megatron-bridge bindssave_fileat import time, andsave_filelooks upserialize_fileon each call, so patchingsave_filewould miss the bridge path.os.replace, so a crashed copy does not leave a truncated shard.Checklist Before Submitting
McoreCheckpointConfig.safetensors_staging_dir. Actor and critic yaml comments and the save helpers link there.tests/utils/ckpt/test_megatron_checkpoint_manager_on_cpu.pymodule.cpu_unit_tests.ymlalready collectstests/**/test_*_on_cpu.py.ci-requestchannel. GPU CI is not requested yet.recipesubmodule.AI assistance (Cursor) was used to split this slice out of #7570 and prepare the PR. Human review of every changed line remains the submitter's responsibility.