{"record":{"id":"14340d636882e6eb","repo":"sgl-project/sglang","slug":"func-path-should-contain-both-module-name-and-func","errorCode":null,"errorMessage":"func_path should contain both module name and func name (such as 'module.func')","messagePattern":"func_path should contain both module name and func name \\(such as 'module\\.func'\\)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/utils/common.py","lineNumber":3971,"sourceCode":"\n    def __getitem__(self, key):\n        return self.value[key]\n\n    def __setitem__(self, key, value):\n        self.value[key] = value\n\n    @property\n    def value(self):\n        if self._creator is not None:\n            self._value = self._creator()\n            self._creator = None\n        return self._value\n\n\ndef dynamic_import(func_path: str):\n    parts = func_path.split(\".\")\n    if len(parts) < 2:\n        raise ValueError(\n            \"func_path should contain both module name and func name (such as 'module.func')\"\n        )\n    module_path = \".\".join(parts[:-1])\n    func_name = parts[-1]\n    module = importlib.import_module(module_path)\n    func = getattr(module, func_name)\n    return func\n\n\ndef gc_object_counts():\n    import gc\n\n    g0 = len(gc.get_objects(0))\n    g1 = len(gc.get_objects(1))\n    g2 = len(gc.get_objects(2))\n    return g0, g1, g2\n\n","sourceCodeStart":3953,"sourceCodeEnd":3989,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/utils/common.py#L3953-L3989","documentation":"dynamic_import splits func_path on '.' and requires at least two parts so it can derive module_path + func_name. A bare name like 'foo' (no dot) cannot identify a module and is rejected.","triggerScenarios":"Passing 'mymodel', 'run', or '' to dynamic_import — any string without a '.' separator.","commonSituations":"Config strings for pluggable attention/workload functions where the user forgot the module qualifier, or an empty default leaked through.","solutions":["Use fully qualified 'package.module.func' form","Validate the config string contains a '.' before passing","Default the config to a shipped fully-qualified function"],"exampleFix":"# before\nfn = dynamic_import(\"eplb\")\n# after\nfn = dynamic_import(\"sglang.srt.eplb.eplb_manager\")","handlingStrategy":"validation","validationCode":"assert \".\" in func_path and len(func_path.split(\".\")) >= 2","typeGuard":"def is_qualified_path(s: str) -> bool:\n    return isinstance(s, str) and s.count(\".\") >= 1 and all(s.split(\".\"))","tryCatchPattern":null,"preventionTips":["Always configure fully qualified 'module.sub.func' strings","Validate config strings at startup"],"tags":["dynamic-import","configuration","valueerror"],"backgroundTag":"invalid-module-path","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}