{"record":{"id":"607e4452ed41294e","repo":"huggingface/smolagents","slug":"expected-class-or-callable-got-type-obj","errorCode":null,"errorMessage":"Expected class or callable, got {type(obj)}","messagePattern":"Expected class or callable, got (.+?)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/smolagents/utils.py","lineNumber":397,"sourceCode":"    In a dynamic environment (e.g.: Jupyter, IPython), if this fails,\n    falls back to retrieving the source code from the current interactive shell session.\n\n    Args:\n        obj: A class or callable object (e.g.: function, method)\n\n    Returns:\n        str: The source code of the object, dedented and stripped\n\n    Raises:\n        TypeError: If object is not a class or callable\n        OSError: If source code cannot be retrieved from any source\n        ValueError: If source cannot be found in IPython history\n\n    Note:\n        TODO: handle Python standard REPL\n    \"\"\"\n    if not (isinstance(obj, type) or callable(obj)):\n        raise TypeError(f\"Expected class or callable, got {type(obj)}\")\n\n    inspect_error = None\n    try:\n        # Handle dynamically created classes\n        source = getattr(obj, \"__source__\", None) or inspect.getsource(obj)\n        return dedent(source).strip()\n    except OSError as e:\n        # let's keep track of the exception to raise it if all further methods fail\n        inspect_error = e\n    try:\n        import IPython\n\n        shell = IPython.get_ipython()\n        if not shell:\n            raise ImportError(\"No active IPython shell found\")\n        all_cells = \"\\n\".join(shell.user_ns.get(\"In\", [])).strip()\n        if not all_cells:\n            raise ValueError(\"No code cells found in IPython session\")","sourceCodeStart":379,"sourceCodeEnd":415,"githubUrl":"https://github.com/huggingface/smolagents/blob/30bb1161095dbae2271e6bc3cc4c219cc3897a57/src/smolagents/utils.py#L379-L415","documentation":"get_source(obj) requires a class or callable to extract its source via inspect/ast. Passing anything else (an instance used wrongly, an int, None, a module) raises this TypeError immediately before any inspection is attempted.","triggerScenarios":"Calling smolagents.utils.get_source (or @tool-decorated serialization paths like instance_to_source) with a non-class, non-callable object such as get_source(42) or get_source(None).","commonSituations":"Programmatically iterating over objects and accidentally passing instances instead of their classes (obj instead of type(obj)); None leaking from a failed lookup.","solutions":["Pass the class or function itself, e.g. MyTool not MyTool()","Guard call sites with isinstance(obj, type) or callable(obj) before calling","Check for None/early-return failures upstream that produce the bad value"],"exampleFix":"# before\nsrc = get_source(tool_instance)\n\n# after\nsrc = get_source(type(tool_instance))","handlingStrategy":"type-guard","validationCode":"if not (isinstance(obj, type) or callable(obj)):\n    raise TypeError('pass a class or function')\nsrc = get_source(obj)","typeGuard":"def is_class_or_callable(obj) -> bool:\n    return isinstance(obj, type) or callable(obj)","tryCatchPattern":"try:\n    get_source(obj)\nexcept TypeError as e:\n    if 'Expected class or callable' in str(e):\n        obj = type(obj) if not isinstance(obj, type) else obj\n        src = get_source(obj)","preventionTips":["Pass classes/functions, never instances, to source extraction","Validate dynamic inputs before introspection APIs"],"tags":["smolagents","utils","type-guard","introspection"],"backgroundTag":"invalid-argument-type","analyzedSha":"30bb1161095dbae2271e6bc3cc4c219cc3897a57","analyzedAt":"2026-08-28T18:52:54.169Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}