1919from typing import Any , Optional
2020
2121from absl import flags
22- import contextlib
2322import datetime
2423from etils import epath
2524from flax import nnx
@@ -661,14 +660,12 @@ def _restore_grain_iterator(
661660 if isinstance (data_iterator , RemoteIteratorWrapper ):
662661 grain_restore_args = GrainCheckpointRestore (item = data_iterator )
663662 restored_state = checkpoint_manager .restore (step , args = Composite (items = checkpoint_args , iter = grain_restore_args ))
664- _assert_no_shaped_dtype_struct (restored_state )
665663 return (restored_state , None )
666664
667665 # ElasticIterator: one shared `process_0.json` regardless of shard count.
668666 if not isinstance (data_iterator , list ) and isinstance (data_iterator .local_iterator , ElasticIterator ):
669667 grain_restore_args = GrainCheckpointRestore (item = data_iterator .local_iterator )
670668 restored_state = checkpoint_manager .restore (step , args = Composite (items = checkpoint_args , iter = grain_restore_args ))
671- _assert_no_shaped_dtype_struct (restored_state )
672669 return (restored_state , None )
673670
674671 directory = checkpoint_manager .directory / str (step ) / "iter"
@@ -717,67 +714,9 @@ def _restore_grain_iterator(
717714
718715 # Call restore once with the composed arguments
719716 restored_state = checkpoint_manager .restore (step , args = Composite (items = checkpoint_args , iter = grain_restore_args ))
720- _assert_no_shaped_dtype_struct (restored_state )
721717 return (restored_state , None )
722718
723719
724- def is_structural_or_shape_mismatch (e : Exception ) -> bool :
725- """Helper to check if an exception is likely a PyTree structure or shape mismatch."""
726- if not isinstance (e , (ValueError , TypeError )):
727- return False
728- msg = str (e ).lower ()
729- mismatch_keywords = [
730- "mismatch" ,
731- "structure" ,
732- "shape" ,
733- "tree" ,
734- "leaf" ,
735- "leaves" ,
736- "paths matched" ,
737- "shapedtypestruct" ,
738- "invalid type" ,
739- ]
740- return any (kw in msg for kw in mismatch_keywords )
741-
742-
743- def _assert_no_shaped_dtype_struct (pytree ):
744- """Asserts that there are no jax.ShapeDtypeStruct leaves in the restored pytree."""
745- if isinstance (pytree , jax .ShapeDtypeStruct ):
746- raise ValueError (
747- "Some parameters in the restored state remained as ShapeDtypeStruct"
748- f" (indicating structure mismatch): { pytree } ."
749- )
750-
751- if hasattr (pytree , "keys" ) and hasattr (pytree , "__getitem__" ):
752- for k in pytree .keys ():
753- _assert_no_shaped_dtype_struct (pytree [k ])
754- elif isinstance (pytree , (list , tuple )):
755- for v in pytree :
756- _assert_no_shaped_dtype_struct (v )
757- else :
758- leaves = jax .tree_util .tree_leaves (pytree )
759- if len (leaves ) == 1 and leaves [0 ] is pytree :
760- return
761- for leaf in leaves :
762- _assert_no_shaped_dtype_struct (leaf )
763-
764-
765- @contextlib .contextmanager
766- def handle_checkpoint_mismatch (context_name : str , path : str ):
767- """Context manager to intercept PyTree/shape mismatches and raise descriptive errors."""
768- try :
769- yield
770- except Exception as e :
771- if is_structural_or_shape_mismatch (e ):
772- raise ValueError (
773- f"Failed to { context_name } from { path } . This is often caused by a"
774- " mismatch in the 'scan_layers' configuration (stacked vs unstacked)"
775- " between your current execution command and the saved checkpoint."
776- f" Original error: { e } "
777- ) from e
778- raise
779-
780-
781720def load_state_if_possible (
782721 checkpoint_manager : CheckpointManager | None ,
783722 data_iterator : MultiHostDataLoadIterator | list [MultiHostDataLoadIterator ] | None ,
@@ -860,30 +799,26 @@ def map_to_pspec(data):
860799 (EmergencyCheckpointManager , EmergencyReplicatorCheckpointManager ),
861800 ):
862801 checkpoint_path = str (checkpoint_manager .directory / str (step ) / "items" )
863- with handle_checkpoint_mismatch ("restore NNX checkpoint" , checkpoint_path ):
864- restored_nnx = _load_linen_checkpoint_into_nnx (
865- checkpoint_path ,
866- abstract_unboxed_pre_state ,
867- checkpoint_storage_concurrent_gb ,
868- use_ocdbt ,
869- use_zarr3 ,
870- )
871- _assert_no_shaped_dtype_struct (restored_nnx )
802+ restored_nnx = _load_linen_checkpoint_into_nnx (
803+ checkpoint_path ,
804+ abstract_unboxed_pre_state ,
805+ checkpoint_storage_concurrent_gb ,
806+ use_ocdbt ,
807+ use_zarr3 ,
808+ )
872809 return ({"items" : restored_nnx }, None )
873810
874811 if isinstance (abstract_unboxed_pre_state , nnx .State ) and isinstance (
875812 checkpoint_manager ,
876813 (EmergencyCheckpointManager , EmergencyReplicatorCheckpointManager ),
877814 ):
878815 checkpoint_path = str (checkpoint_manager .directory / str (step ))
879- with handle_checkpoint_mismatch ("restore emergency NNX checkpoint" , checkpoint_path ):
880- restored = _restore_emergency_linen_checkpoint_into_nnx (
881- checkpoint_manager ,
882- step ,
883- abstract_unboxed_pre_state ,
884- map_to_pspec ,
885- )
886- _assert_no_shaped_dtype_struct (restored )
816+ restored = _restore_emergency_linen_checkpoint_into_nnx (
817+ checkpoint_manager ,
818+ step ,
819+ abstract_unboxed_pre_state ,
820+ map_to_pspec ,
821+ )
887822 return (
888823 restored ,
889824 None ,
@@ -902,49 +837,46 @@ def map_to_pspec(data):
902837 )
903838
904839 checkpoint_path = str (checkpoint_manager .directory / str (step ))
905- with handle_checkpoint_mismatch ("restore checkpoint" , checkpoint_path ):
906- match (checkpoint_manager , dataset_type , data_iterator ):
907- # Case 1: Matches if 'checkpoint_manager' is an instance of either EmergencyCheckpointManager
908- # or EmergencyReplicatorCheckpointManager. The '_' indicates that 'dataset_type' and
909- # 'data_iterator' can be any value and aren't used in this pattern.
910- case (checkpoint_manager , _, _) if isinstance (
911- checkpoint_manager ,
912- (
913- EmergencyCheckpointManager ,
914- EmergencyReplicatorCheckpointManager ,
915- ),
916- ):
917- restored = checkpoint_manager .restore (step , args = Composite (state = checkpoint_args )).state
918- _assert_no_shaped_dtype_struct (restored )
919- return (
920- restored ,
921- None ,
922- )
923- # Case 2: Matches if dataset type is "grain" and the data iterator is not a
924- # PlaceHolderDataIterator and a specific checkpoint file exists for the iterator
925- case (
840+ match (checkpoint_manager , dataset_type , data_iterator ):
841+ # Case 1: Matches if 'checkpoint_manager' is an instance of either EmergencyCheckpointManager
842+ # or EmergencyReplicatorCheckpointManager. The '_' indicates that 'dataset_type' and
843+ # 'data_iterator' can be any value and aren't used in this pattern.
844+ case (checkpoint_manager , _, _) if isinstance (
845+ checkpoint_manager ,
846+ (
847+ EmergencyCheckpointManager ,
848+ EmergencyReplicatorCheckpointManager ,
849+ ),
850+ ):
851+ restored = checkpoint_manager .restore (step , args = Composite (state = checkpoint_args )).state
852+ return (
853+ restored ,
854+ None ,
855+ )
856+ # Case 2: Matches if dataset type is "grain" and the data iterator is not a
857+ # PlaceHolderDataIterator and a specific checkpoint file exists for the iterator
858+ case (
859+ checkpoint_manager ,
860+ dataset_type ,
861+ data_iterator ,
862+ ) if (
863+ dataset_type == "grain"
864+ and data_iterator
865+ and not isinstance (data_iterator , PlaceHolderDataIterator )
866+ and (checkpoint_manager .directory / str (step ) / "iter" ).exists ()
867+ ):
868+ return _restore_grain_iterator (
926869 checkpoint_manager ,
927- dataset_type ,
870+ step ,
928871 data_iterator ,
929- ) if (
930- dataset_type == "grain"
931- and data_iterator
932- and not isinstance (data_iterator , PlaceHolderDataIterator )
933- and (checkpoint_manager .directory / str (step ) / "iter" ).exists ()
934- ):
935- return _restore_grain_iterator (
936- checkpoint_manager ,
937- step ,
938- data_iterator ,
939- checkpoint_args ,
940- expansion_factor_real_data ,
941- )
942- # Case 3: Default/Fallback case.
943- # This case acts as a wildcard ('_') and matches if none of the preceding cases were met.
944- case _:
945- restored = checkpoint_manager .restore (step , args = Composite (items = checkpoint_args ))
946- _assert_no_shaped_dtype_struct (restored )
947- return (restored , None )
872+ checkpoint_args ,
873+ expansion_factor_real_data ,
874+ )
875+ # Case 3: Default/Fallback case.
876+ # This case acts as a wildcard ('_') and matches if none of the preceding cases were met.
877+ case _:
878+ restored = checkpoint_manager .restore (step , args = Composite (items = checkpoint_args ))
879+ return (restored , None )
948880
949881 if source_checkpoint_layout == "safetensors_dynamic" :
950882 path = load_parameters_from_path or load_full_state_from_path
@@ -957,30 +889,26 @@ def map_to_pspec(data):
957889 else :
958890 params = abstract_unboxed_pre_state .params
959891
960- with handle_checkpoint_mismatch ("load parameters" , load_parameters_from_path ):
961- restored_params = load_params_from_path (
962- load_parameters_from_path ,
963- params ,
964- checkpoint_storage_concurrent_gb ,
965- use_ocdbt = use_ocdbt ,
966- use_zarr3 = use_zarr3 ,
967- )
968- _assert_no_shaped_dtype_struct (restored_params )
892+ restored_params = load_params_from_path (
893+ load_parameters_from_path ,
894+ params ,
895+ checkpoint_storage_concurrent_gb ,
896+ use_ocdbt = use_ocdbt ,
897+ use_zarr3 = use_zarr3 ,
898+ )
969899 return None , restored_params
970900 elif load_full_state_from_path != "" :
971901 max_logging .log (f"Loading full state from path: { load_full_state_from_path } " )
972- with handle_checkpoint_mismatch ("load full state" , load_full_state_from_path ):
973- restored_state = _load_full_state_from_path (
974- path = load_full_state_from_path ,
975- abstract_unboxed_pre_state = abstract_unboxed_pre_state ,
976- enable_orbax_v1 = enable_orbax_v1 ,
977- checkpoint_conversion_fn = checkpoint_conversion_fn ,
978- source_checkpoint_layout = source_checkpoint_layout ,
979- checkpoint_storage_concurrent_gb = checkpoint_storage_concurrent_gb ,
980- use_ocdbt = use_ocdbt ,
981- use_zarr3 = use_zarr3 ,
982- )
983- _assert_no_shaped_dtype_struct (restored_state )
902+ restored_state = _load_full_state_from_path (
903+ path = load_full_state_from_path ,
904+ abstract_unboxed_pre_state = abstract_unboxed_pre_state ,
905+ enable_orbax_v1 = enable_orbax_v1 ,
906+ checkpoint_conversion_fn = checkpoint_conversion_fn ,
907+ source_checkpoint_layout = source_checkpoint_layout ,
908+ checkpoint_storage_concurrent_gb = checkpoint_storage_concurrent_gb ,
909+ use_ocdbt = use_ocdbt ,
910+ use_zarr3 = use_zarr3 ,
911+ )
984912 return {"items" : restored_state }, None
985913 else :
986914 max_logging .log ("No existing checkpoints found, not restoring checkpoint." )
0 commit comments