{"record":{"id":"28f73a4d7354efb3","repo":"Lightning-AI/pytorch-lightning","slug":"hparams-must-be-dictionary","errorCode":null,"errorMessage":"hparams must be dictionary","messagePattern":"hparams must be dictionary","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/lightning/pytorch/core/saving.py","lineNumber":368,"sourceCode":"\n    # saving with OmegaConf objects\n    if _OMEGACONF_AVAILABLE and use_omegaconf:\n        from omegaconf import OmegaConf\n        from omegaconf.dictconfig import DictConfig\n        from omegaconf.errors import UnsupportedValueType, ValidationError\n\n        # deepcopy: hparams from user shouldn't be resolved\n        hparams = deepcopy(hparams)\n        hparams = apply_to_collection(hparams, DictConfig, OmegaConf.to_container, resolve=True)\n        with fs.open(config_yaml, \"w\", encoding=\"utf-8\") as fp:\n            try:\n                OmegaConf.save(hparams, fp)\n                return\n            except (UnsupportedValueType, ValidationError):\n                pass\n\n    if not isinstance(hparams, dict):\n        raise TypeError(\"hparams must be dictionary\")\n\n    hparams_allowed = {}\n    # drop parameters which contain some strange datatypes as fsspec\n    for k, v in hparams.items():\n        try:\n            v = v.name if isinstance(v, Enum) else v\n            yaml.dump(v)\n        except (TypeError, ValueError):\n            warn(f\"Skipping '{k}' parameter because it is not possible to safely dump to YAML.\")\n            hparams[k] = type(v).__name__\n        else:\n            hparams_allowed[k] = v\n\n    # saving the standard way\n    with fs.open(config_yaml, \"w\", newline=\"\") as fp:\n        yaml.dump(hparams_allowed, fp)\n\n","sourceCodeStart":350,"sourceCodeEnd":386,"githubUrl":"https://github.com/Lightning-AI/pytorch-lightning/blob/9fed5c27d2a62ff0efd6c3573599921d6ff67c14/src/lightning/pytorch/core/saving.py#L350-L386","documentation":"TypeError from save_hparams_to_yaml after Namespace/AttributeDict conversion and the OmegaConf fallback path: if hparams is still not a plain dict, it cannot be serialized to YAML by this function.","triggerScenarios":"Passing a dataclass, omegaconf DictConfig that failed OmegaConf.save with UnsupportedValueType/ValidationError and fell through, a custom Mapping subclass, or a string/None as hparams.","commonSituations":"Hyperparameters stored in a dataclass or a DictConfig containing non-serializable values (tensors, custom objects); the OmegaConf save attempt fails, then the dict check trips.","solutions":["Convert to a plain dict first: hparams = dict(hparams) (or OmegaConf.to_container(hparams, resolve=True) for configs)","Replace non-serializable values (tensors, objects) with primitives before saving","For dataclasses use dataclasses.asdict(hparams)"],"exampleFix":"// before\nsave_hparams_to_yaml(path, OmegaConf.create({\"lr\": tensor_obj}))  # falls through\n// after\nfrom omegaconf import OmegaConf\nhparams = OmegaConf.to_container(cfg, resolve=True)\nsave_hparams_to_yaml(path, hparams)","handlingStrategy":"type-guard","validationCode":"if not isinstance(hparams, dict):\n    hparams = OmegaConf.to_container(hparams, resolve=True) if OmegaConf.is_config(hparams) else dict(hparams)","typeGuard":"def is_plain_dict(x) -> bool:\n    return type(x) is dict","tryCatchPattern":null,"preventionTips":["Normalize hparams to dict early in your save path","Resolve OmegaConf configs and replace tensors/objects before serialization"],"tags":["lightning","hparams","yaml","type-error","serialization"],"backgroundTag":"invalid-input-type","analyzedSha":"9fed5c27d2a62ff0efd6c3573599921d6ff67c14","analyzedAt":"2026-08-28T11:52:41.083Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}