{"record":{"id":"268a0e6ea0effa25","repo":"huggingface/pytorch-image-models","slug":"please-provide-hook-fns-for-each-hook-fn-locs","errorCode":null,"errorMessage":"Please provide `hook_fns` for each `hook_fn_locs`, their lengths are different.","messagePattern":"Please provide `hook_fns` for each `hook_fn_locs`, their lengths are different\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"timm/utils/model.py","lineNumber":73,"sourceCode":"    Arguments:\n        model (nn.Module): model from which we will extract the activation stats\n        hook_fn_locs (List[str]): List of `hook_fn` locations based on Unix type string \n            matching with the name of model's modules. \n        hook_fns (List[Callable]): List of hook functions to be registered at every\n            module in `layer_names`.\n    \n    Inspiration from https://docs.fast.ai/callback.hook.html.\n\n    Refer to https://gist.github.com/amaarora/6e56942fcb46e67ba203f3009b30d950 for an example \n    on how to plot Signal Propagation Plots using `ActivationStatsHook`.\n    \"\"\"\n\n    def __init__(self, model, hook_fn_locs, hook_fns):\n        self.model = model\n        self.hook_fn_locs = hook_fn_locs\n        self.hook_fns = hook_fns\n        if len(hook_fn_locs) != len(hook_fns):\n            raise ValueError(\"Please provide `hook_fns` for each `hook_fn_locs`, \\\n                their lengths are different.\")\n        self.stats = dict((hook_fn.__name__, []) for hook_fn in hook_fns)\n        for hook_fn_loc, hook_fn in zip(hook_fn_locs, hook_fns):\n            self.register_hook(hook_fn_loc, hook_fn)\n\n    def _create_hook(self, hook_fn):\n        def append_activation_stats(module, input, output):\n            out = hook_fn(module, input, output)\n            self.stats[hook_fn.__name__].append(out)\n\n        return append_activation_stats\n\n    def register_hook(self, hook_fn_loc, hook_fn):\n        for name, module in self.model.named_modules():\n            if not fnmatch.fnmatch(name, hook_fn_loc):\n                continue\n            module.register_forward_hook(self._create_hook(hook_fn))\n","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/huggingface/pytorch-image-models/blob/9a5261e31b3b5128526eb2658333b4c0a54464ae/timm/utils/model.py#L55-L91","documentation":"BenchmarkHook / hook-registration helper in timm.utils.model requires hook_fn_locs and hook_fns to be parallel lists: one hook function per location. ValueError is raised at __init__ when len(hook_fn_locs) != len(hook_fns).","triggerScenarios":"Passing ModelEmlaHook-style API e.g. BenchmarkHook(model, ['blocks.0.attn', 'blocks.1.attn'], [my_hook_fn]) with 2 locs but 1 fn, or passing a single function instead of a list of functions.","commonSituations":"Reusing one hook function for several locations without wrapping it in a list comprehension; adding a new location but forgetting the corresponding function; passing a bare function where a list is expected.","solutions":["Make the lists equal length, e.g. hook_fns=[my_hook_fn] * len(hook_fn_locs) if the same fn is reused","Double-check you passed a list (not a scalar) for both arguments when there are multiple hooks"],"exampleFix":"# before\nhooks = BenchmarkHook(model, ['blocks.0.attn', 'blocks.1.attn'], [my_hook_fn])\n# after\nhooks = BenchmarkHook(model, ['blocks.0.attn', 'blocks.1.attn'], [my_hook_fn, my_hook_fn])","handlingStrategy":"validation","validationCode":"assert len(hook_fn_locs) == len(hook_fns), 'locs and fns must align'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Build both lists in one comprehension so they stay in sync","Reuse one fn via [fn] * len(locs)"],"tags":["hooks","argument-validation","timm"],"backgroundTag":"argument-length-mismatch","analyzedSha":"9a5261e31b3b5128526eb2658333b4c0a54464ae","analyzedAt":"2026-08-27T02:34:25.417Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}