{"record":{"id":"a0140e0a2ada7151","repo":"Lightning-AI/pytorch-lightning","slug":"schedule-should-be-a-callable-found-schedule","errorCode":null,"errorMessage":"Schedule should be a callable. Found: {schedule}","messagePattern":"Schedule should be a callable\\. Found: (.+?)","errorType":"exception","errorClass":"MisconfigurationException","httpStatus":null,"severity":"error","filePath":"src/lightning/pytorch/profilers/pytorch.py","lineNumber":342,"sourceCode":"                raise KeyError(\n                    f\"Found invalid table_kwargs key: {key}. This is already a positional argument of the Profiler.\"\n                )\n            valid_table_keys = set(inspect.signature(EventList.table).parameters.keys()) - {\n                \"self\",\n                \"sort_by\",\n                \"row_limit\",\n            }\n            if key not in valid_table_keys:\n                raise KeyError(f\"Found invalid table_kwargs key: {key}. Should be within {valid_table_keys}.\")\n\n    def _init_kineto(self, profiler_kwargs: Any) -> None:\n        has_schedule = \"schedule\" in profiler_kwargs\n        self._has_on_trace_ready = \"on_trace_ready\" in profiler_kwargs\n\n        schedule = profiler_kwargs.get(\"schedule\", None)\n        if schedule is not None:\n            if not callable(schedule):\n                raise MisconfigurationException(f\"Schedule should be a callable. Found: {schedule}\")\n            action = schedule(0)\n            if not isinstance(action, ProfilerAction):\n                raise MisconfigurationException(\n                    f\"Schedule should return a `torch.profiler.ProfilerAction`. Found: {action}\"\n                )\n        self._default_schedule()\n        schedule = schedule if has_schedule else self._default_schedule()\n        self._schedule = ScheduleWrapper(schedule) if schedule is not None else schedule\n        self._profiler_kwargs[\"schedule\"] = self._schedule\n\n        activities = profiler_kwargs.get(\"activities\", None)\n        self._profiler_kwargs[\"activities\"] = activities or self._default_activities()\n        self._export_to_flame_graph = profiler_kwargs.get(\"export_to_flame_graph\", False)\n        self._metric = profiler_kwargs.get(\"metric\", \"self_cpu_time_total\")\n        with_stack = profiler_kwargs.get(\"with_stack\", False) or self._export_to_flame_graph\n        self._profiler_kwargs[\"with_stack\"] = with_stack\n\n    @property","sourceCodeStart":324,"sourceCodeEnd":360,"githubUrl":"https://github.com/Lightning-AI/pytorch-lightning/blob/9fed5c27d2a62ff0efd6c3573599921d6ff67c14/src/lightning/pytorch/profilers/pytorch.py#L324-L360","documentation":"When PyTorchProfiler is created with a schedule in profiler_kwargs (e.g. via Trainer(profiler=PyTorchProfiler(...)) with schedule), _init_kineto requires it to be a callable — normally the result of torch.profiler.schedule(...). A non-callable (e.g. a string or dict) raises MisconfigurationException.","triggerScenarios":"Passing profiler_kwargs={'schedule': torch.profiler.schedule(wait=1, warmup=1, active=3)} is correct; passing {'schedule': 'wait=1,warmup=1'} or a dict/config object instead of the callable produced by torch.profiler.schedule() triggers it.","commonSituations":"Loading profiler config from YAML/JSON and passing the raw string/dict instead of constructing a schedule; forgetting the parentheses so a function reference vs. its result confusion arises; wrapping schedule in a non-callable wrapper.","solutions":["Create the schedule with torch.profiler.schedule(wait=..., warmup=..., active=..., repeat=...) and pass that object","If loading config, convert the parsed settings into a call: functools.partial(torch.profiler.schedule, **cfg)","Omit schedule entirely if you don't need step-based profiling"],"exampleFix":"# before\nprofiler = PyTorchProfiler(profiler_kwargs={\"schedule\": {\"wait\": 1, \"warmup\": 1, \"active\": 3}})\n\n# after\nprofiler = PyTorchProfiler(\n    schedule=torch.profiler.schedule(wait=1, warmup=1, active=3, repeat=1)\n)","handlingStrategy":"type-guard","validationCode":"if schedule is not None:\n    assert callable(schedule), f\"schedule must be callable, got {type(schedule)}\"","typeGuard":"def is_valid_schedule(s) -> bool:\n    import inspect\n    from torch.profiler import ProfilerAction\n    if not callable(s):\n        return False\n    try:\n        return isinstance(s(0), ProfilerAction)\n    except Exception:\n        return False","tryCatchPattern":"try:\n    profiler = PyTorchProfiler(schedule=schedule)\nexcept MisconfigurationException as e:\n    profiler = PyTorchProfiler(schedule=torch.profiler.schedule(wait=1, warmup=1, active=3))","preventionTips":["Always build schedules via torch.profiler.schedule(...)","Never pass raw strings/dicts from config as schedule","Validate callable config values at load time"],"tags":["profiler","schedule","type-error","pytorch-lightning"],"backgroundTag":"invalid-argument-type","analyzedSha":"9fed5c27d2a62ff0efd6c3573599921d6ff67c14","analyzedAt":"2026-08-28T11:52:41.083Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}