{"record":{"id":"6720a248ec3681b2","repo":"fishaudio/fish-speech","slug":"callbacks-config-must-be-a-dictconfig","errorCode":null,"errorMessage":"Callbacks config must be a DictConfig!","messagePattern":"Callbacks config must be a DictConfig!","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"fish_speech/utils/instantiators.py","lineNumber":23,"sourceCode":"from pytorch_lightning import Callback\nfrom pytorch_lightning.loggers import Logger\n\nfrom .logger import RankedLogger\n\nlog = RankedLogger(__name__, rank_zero_only=True)\n\n\ndef instantiate_callbacks(callbacks_cfg: DictConfig) -> List[Callback]:\n    \"\"\"Instantiates callbacks from config.\"\"\"\n\n    callbacks: List[Callback] = []\n\n    if not callbacks_cfg:\n        log.warning(\"No callback configs found! Skipping..\")\n        return callbacks\n\n    if not isinstance(callbacks_cfg, DictConfig):\n        raise TypeError(\"Callbacks config must be a DictConfig!\")\n\n    for _, cb_conf in callbacks_cfg.items():\n        if isinstance(cb_conf, DictConfig) and \"_target_\" in cb_conf:\n            log.info(f\"Instantiating callback <{cb_conf._target_}>\")\n            callbacks.append(hydra.utils.instantiate(cb_conf))\n\n    return callbacks\n\n\ndef instantiate_loggers(logger_cfg: DictConfig) -> List[Logger]:\n    \"\"\"Instantiates loggers from config.\"\"\"\n\n    logger: List[Logger] = []\n\n    if not logger_cfg:\n        log.warning(\"No logger configs found! Skipping...\")\n        return logger\n","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/fishaudio/fish-speech/blob/befe4001745417f8c42131739d862b8a6fdbd15a/fish_speech/utils/instantiators.py#L5-L41","documentation":"Hydra-style instantiate_callbacks requires the callbacks config node to be an OmegaConf DictConfig. Passing a plain dict, a list, or a structured config of another type raises TypeError immediately.","triggerScenarios":"Calling train() with cfg.callbacks that is a python dict (e.g. after OmegaConf.to_container) or a ListConfig.","commonSituations":"Programmatically composing configs and converting them to native dicts; overriding callbacks via a custom YAML that produces a list; version drift in the hydra-template train loop.","solutions":["Wrap the node: instantiate_callbacks(OmegaConf.create(cfg.callbacks)) or keep the whole cfg as DictConfig","Ensure the callbacks section maps names to {_target_: ...} entries, not a list","If merging programmatically, use OmegaConf.merge instead of dict updates"],"exampleFix":"# before\ninstantiate_callbacks({\"checkpoint\": {\"_target_\": \"...\"}})\n# after\nfrom omegaconf import OmegaConf\ninstantiate_callbacks(OmegaConf.create({\"checkpoint\": {\"_target_\": \"...\"}}))","handlingStrategy":"type-guard","validationCode":"from omegaconf import DictConfig\nif callbacks_cfg is not None and not isinstance(callbacks_cfg, DictConfig):\n    callbacks_cfg = OmegaConf.create(callbacks_cfg)","typeGuard":"def is_dict_config(x):\n    from omegaconf import DictConfig\n    return x is None or isinstance(x, DictConfig)","tryCatchPattern":null,"preventionTips":["Never call OmegaConf.to_container on nodes passed to instantiators","Compose configs with OmegaConf.merge"],"tags":["hydra","config","type-error"],"backgroundTag":"config-type-mismatch","analyzedSha":"befe4001745417f8c42131739d862b8a6fdbd15a","analyzedAt":"2026-08-27T21:31:45.703Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}