{"record":{"id":"5c39763f80d6d847","repo":"xtekky/gpt4free","slug":"cannot-find-submodule-name-in-workspace-module","errorCode":null,"errorMessage":"Cannot find submodule '{name}' in workspace module '{base}'.","messagePattern":"Cannot find submodule '(.+?)' in workspace module '(.+?)'\\.","errorType":"exception","errorClass":"ImportError","httpStatus":null,"severity":"error","filePath":"g4f/mcp/pa_provider.py","lineNumber":478,"sourceCode":"                    raise ImportError(\n                        f\"'{name}' is not available in the restricted os shim.\"\n                    )\n            return obj\n        if base not in allowed:\n            # Before rejecting, check if it's a workspace module (sibling .py file).\n            workspace = get_workspace_dir()\n            ws_module = _load_workspace_module(\n                base, workspace, globals, fromlist, level\n            )\n            if ws_module is not None:\n                # Handle submodule imports (e.g. \"pkg.sub\")\n                if name != base:\n                    # Try to resolve the full dotted path from the loaded module\n                    obj = ws_module\n                    for part in name.split(\".\")[1:]:\n                        obj = getattr(obj, part, None)\n                        if obj is None:\n                            raise ImportError(\n                                f\"Cannot find submodule '{name}' in workspace module '{base}'.\"\n                            )\n                    return obj\n                return ws_module\n            raise ImportError(\n                f\"Import of '{name}' is not allowed in safe execution mode.\\n\"\n                f\"Allowed top-level modules: {', '.join(sorted(allowed))}\"\n            )\n        # Explicit allowlist takes priority over the blocklist below.\n        # This permits e.g. \"g4f.Provider.helper\" even though \"g4f.Provider\"\n        # is blocked.\n        for allowed_sub in _ALLOWED_G4F_SUBPATHS:\n            if name == allowed_sub or name.startswith(allowed_sub + \".\"):\n                return original(name, globals, locals, fromlist, level)\n        # Block sensitive g4f submodules even though g4f itself is allowed.\n        if name in _BLOCKED_SUBMODULES:\n            raise ImportError(\n                f\"Import of '{name}' is not allowed inside a .pa.py sandbox \"","sourceCodeStart":460,"sourceCodeEnd":496,"githubUrl":"https://github.com/xtekky/gpt4free/blob/973504e1770928ed5fb82f43da528f441ad9ddc3/g4f/mcp/pa_provider.py#L460-L496","documentation":"Raised by the sandbox import hook when a dotted import's top-level module resolves to a sibling workspace .py file, but a later path component is missing as an attribute on that module. Example: 'import mypkg.helpers' where workspace contains mypkg.py but mypkg.py defines no 'helpers'. The sandbox first loads the sibling file via _load_workspace_module, then walks the remaining dotted parts with getattr and fails on the first missing attribute.","triggerScenarios":"A .pa.py file imports 'X.sub' where X.py exists in the workspace directory but X does not define/assign 'sub' (no submodule, class, or variable with that name). Also triggered when X.py conditionally defines 'sub' and the defining branch did not run during sandbox execution.","commonSituations":"Splitting a helper across several files with dotted imports as if the workspace were a package; typos in the submodule name; helper module whose import-time code raised earlier so attributes were never set.","solutions":["Verify the exact attribute name exists in the sibling workspace module (no typo, correct case)","Import only the top-level module and access the member via attribute: 'import util; util.format_msg'","Move the needed function/class into the top-level workspace .py file instead of a dotted path","Ensure module-level definitions in the sibling file are unconditional (not inside try/except that swallows errors)"],"exampleFix":"# before\nimport helpers.format\n\n# after (helpers.py is a flat sibling module)\nimport helpers\nhelpers.format(...)","handlingStrategy":"validation","validationCode":"# before executing, verify the sibling module exposes the submodule name\nimport importlib.util, pathlib\nws = get_workspace_dir()\nmod_file = ws / (base + \".py\")\nif mod_file.exists():\n    spec = importlib.util.spec_from_file_location(base, mod_file)\n    m = importlib.util.module_from_spec(spec); spec.loader.exec_module(m)\n    assert hasattr(m, submodule_name), f\"{base} lacks attribute {submodule_name}\"","typeGuard":null,"tryCatchPattern":"try:\n    import mypkg.sub\nexcept ImportError as e:\n    if \"Cannot find submodule\" in str(e):\n        import mypkg  # fall back to top-level import + attribute access","preventionTips":["Import workspace modules by top-level name only and access members via attributes","Keep workspace helper files flat (one module, no pseudo-packages)","Ensure helper attributes are defined unconditionally at module scope"],"tags":["sandbox","import","workspace","pa-provider"],"backgroundTag":null,"analyzedSha":"973504e1770928ed5fb82f43da528f441ad9ddc3","analyzedAt":"2026-08-14T23:45:32.408Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}