{"record":{"id":"98b5d5acd171df3e","repo":"ScrapeGraphAI/Scrapegraph-ai","slug":"cannot-deep-copy-object-of-type-type-obj","errorCode":null,"errorMessage":"Cannot deep copy object of type {type(obj)}","messagePattern":"Cannot deep copy object of type (.+?)","errorType":"error_code","errorClass":"DeepCopyError","httpStatus":null,"severity":"error","filePath":"scrapegraphai/utils/copy.py","lineNumber":71,"sourceCode":"        if isinstance(obj, (list, set)):\n            return type(obj)(safe_deepcopy(v) for v in obj)\n\n        if isinstance(obj, dict):\n            return {k: safe_deepcopy(v) for k, v in obj.items()}\n\n        if isinstance(obj, tuple):\n            return tuple(safe_deepcopy(v) for v in obj)\n\n        if isinstance(obj, frozenset):\n            return frozenset(safe_deepcopy(v) for v in obj)\n\n        if is_boto3_client(obj):\n            return obj\n\n        return copy.copy(obj)\n\n    except Exception as e:\n        raise DeepCopyError(f\"Cannot deep copy object of type {type(obj)}\") from e\n","sourceCodeStart":53,"sourceCodeEnd":72,"githubUrl":"https://github.com/ScrapeGraphAI/Scrapegraph-ai/blob/532dfffbf6ee823a6c9cf8cfedc24a93bf026780/scrapegraphai/utils/copy.py#L53-L72","documentation":"DeepCopyError raised by safe_deepcopy when an exception occurs while deep-copying an object (e.g. unpicklable locks, generators, or objects with broken __deepcopy__). The original exception is chained. safe_deepcopy already special-cases boto3 clients and falls back to copy.copy, so this error means even the fallback path raised.","triggerScenarios":"Passing objects like open sockets, threads/locks, generators, or objects whose __deepcopy__/__reduce__ raise to safe_deepcopy (used in graph __init__ when copying configs).","commonSituations":"Putting a live HTTP client, browser session, or DB connection inside a graph config dict that gets deep-copied at graph construction.","solutions":["Remove non-copyable live resources (clients, sessions, locks) from the config passed to the graph; create them inside nodes","Have the object implement __deepcopy__ returning self or a proper copy","Catch DeepCopyError and construct a fresh instance instead of copying"],"exampleFix":"# before\ngraph = SmartScraperGraph(prompt=..., config={\"client\": boto3.client(\"s3\"), ...})\n# after\nconfig = {\"aws\": {\"region\": \"us-east-1\"}}  # plain data only\ngraph = SmartScraperGraph(prompt=..., config=config)","handlingStrategy":"type-guard","validationCode":"def copyable(cfg):\n    return all(not hasattr(v, \"aclose\") and not isinstance(v, (threading.Lock, type(None), (int, float, str, bool, list, dict))) is False or True for v in []) # simple: keep config JSON-like\nimport json\njson.dumps(config)  # raises early if config holds non-serializable live objects","typeGuard":"def is_safe_to_copy(obj) -> bool:\n    try:\n        copy.deepcopy(obj)\n        return True\n    except Exception:\n        return False","tryCatchPattern":"from scrapegraphai.utils.copy import DeepCopyError\ntry:\n    cfg = safe_deepcopy(config)\nexcept DeepCopyError:\n    cfg = copy.copy(config)  # or rebuild from plain data","preventionTips":["Keep graph config as plain JSON-serializable data","Create clients/sessions lazily inside nodes","Never store boto3 clients, browsers, or sockets in config"],"tags":["deepcopy","config","serialization"],"backgroundTag":"deepcopy-unsupported-object","analyzedSha":"532dfffbf6ee823a6c9cf8cfedc24a93bf026780","analyzedAt":"2026-08-28T15:19:38.821Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}