fishaudio/fish-speech · error · TypeError

Callbacks config must be a DictConfig!

Error message

Callbacks config must be a DictConfig!

What it means

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.

Source

Thrown at fish_speech/utils/instantiators.py:23

from pytorch_lightning import Callback
from pytorch_lightning.loggers import Logger

from .logger import RankedLogger

log = RankedLogger(__name__, rank_zero_only=True)


def instantiate_callbacks(callbacks_cfg: DictConfig) -> List[Callback]:
    """Instantiates callbacks from config."""

    callbacks: List[Callback] = []

    if not callbacks_cfg:
        log.warning("No callback configs found! Skipping..")
        return callbacks

    if not isinstance(callbacks_cfg, DictConfig):
        raise TypeError("Callbacks config must be a DictConfig!")

    for _, cb_conf in callbacks_cfg.items():
        if isinstance(cb_conf, DictConfig) and "_target_" in cb_conf:
            log.info(f"Instantiating callback <{cb_conf._target_}>")
            callbacks.append(hydra.utils.instantiate(cb_conf))

    return callbacks


def instantiate_loggers(logger_cfg: DictConfig) -> List[Logger]:
    """Instantiates loggers from config."""

    logger: List[Logger] = []

    if not logger_cfg:
        log.warning("No logger configs found! Skipping...")
        return logger

View on GitHub (pinned to befe400174)

Solutions

  1. Wrap the node: instantiate_callbacks(OmegaConf.create(cfg.callbacks)) or keep the whole cfg as DictConfig
  2. Ensure the callbacks section maps names to {_target_: ...} entries, not a list
  3. If merging programmatically, use OmegaConf.merge instead of dict updates

Example fix

# before
instantiate_callbacks({"checkpoint": {"_target_": "..."}})
# after
from omegaconf import OmegaConf
instantiate_callbacks(OmegaConf.create({"checkpoint": {"_target_": "..."}}))
Defensive patterns

Strategy: type-guard

Validate before calling

from omegaconf import DictConfig
if callbacks_cfg is not None and not isinstance(callbacks_cfg, DictConfig):
    callbacks_cfg = OmegaConf.create(callbacks_cfg)

Type guard

def is_dict_config(x):
    from omegaconf import DictConfig
    return x is None or isinstance(x, DictConfig)

Prevention

When it happens

Trigger: Calling train() with cfg.callbacks that is a python dict (e.g. after OmegaConf.to_container) or a ListConfig.

Common situations: 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.

Related errors


AI-assisted analysis of fishaudio/fish-speech@befe400174 (2026-08-27). Data as JSON: /api/errors/6720a248ec3681b2. Report an issue: GitHub.