facebookresearch/detectron2 · error · TypeError

target of LazyCall must be a callable or defines a callable!

Error message

target of LazyCall must be a callable or defines a callable! Got {target}

What it means

LazyCall wraps a target that must be a callable (class/function), a string (dotted import path), or a Mapping defining a 'target'. Passing anything else (int, None, list, already-instantiated object) is rejected at construction time.

Source

Thrown at detectron2/config/lazy.py:44

    """
    Wrap a callable so that when it's called, the call will not be executed,
    but returns a dict that describes the call.

    LazyCall object has to be called with only keyword arguments. Positional
    arguments are not yet supported.

    Examples:
    ::
        from detectron2.config import instantiate, LazyCall

        layer_cfg = LazyCall(nn.Conv2d)(in_channels=32, out_channels=32)
        layer_cfg.out_channels = 64   # can edit it afterwards
        layer = instantiate(layer_cfg)
    """

    def __init__(self, target):
        if not (callable(target) or isinstance(target, (str, abc.Mapping))):
            raise TypeError(
                f"target of LazyCall must be a callable or defines a callable! Got {target}"
            )
        self._target = target

    def __call__(self, **kwargs):
        if is_dataclass(self._target):
            # omegaconf object cannot hold dataclass type
            # https://github.com/omry/omegaconf/issues/784
            target = _convert_target_to_string(self._target)
        else:
            target = self._target
        kwargs["_target_"] = target

        return DictConfig(content=kwargs, flags={"allow_objects": True})


def _visit_dict_config(cfg, func):
    """

View on GitHub (pinned to a2f4a8771a)

Solutions

  1. Pass the callable itself: LazyCall(nn.Conv2d)
  2. Or pass a dotted string path: LazyCall("torch.nn.Conv2d")
  3. Or pass a mapping like {'target': 'torch.nn.Conv2d', 'args': [3, 64]}

Example fix

# before
cfg = LazyCall(model.backbone)  # model.backbone is an int like 50
cfg = LazyCall(50)
# after
cfg = LazyCall("detectron2.modeling.backbone.ResNet")
cfg.depth = 50
Defensive patterns

Strategy: type-guard

Validate before calling

assert callable(target) or isinstance(target, (str, dict)), f"invalid LazyCall target: {target!r}"

Type guard

def is_valid_lazy_target(t) -> bool:
    return callable(t) or isinstance(t, str) or (isinstance(t, dict) and ("target" in t))

Prevention

When it happens

Trigger: LazyCall(64), LazyCall(None), LazyCall([nn.Conv2d]), or LazyCall(some_instance) where the instance is neither callable nor a Mapping with a callable 'target'.

Common situations: Confusing LazyCall with instantiate and passing a config value or a fully constructed module; typos where a variable holding a class is actually a number/string without a dotted path.

Related errors


AI-assisted analysis of facebookresearch/detectron2@a2f4a8771a (2026-08-27). Data as JSON: /api/errors/9903045c80d2bc73. Report an issue: GitHub.