{"record":{"id":"3128d4d81c26c481","repo":"ComposioHQ/composio","slug":"request-timed-out-fetching-url-sanitize-url-for","errorCode":null,"errorMessage":"Request timed out fetching URL: {_sanitize_url_for_logging(url)}","messagePattern":"Request timed out fetching URL: (.+?)","errorType":"exception","errorClass":"ErrorUploadingFile","httpStatus":null,"severity":"error","filePath":"python/composio/core/models/_files.py","lineNumber":412,"sourceCode":"        max_size: Maximum response size in bytes (default: 100MB)\n\n    Returns:\n        Tuple of (filename, content_bytes, mimetype)\n\n    Raises:\n        ResponseTooLargeError: If response exceeds max_size\n        ErrorUploadingFile: If fetch fails for other reasons\n    \"\"\"\n    # `safe_get` validates the target, connects to the address it validated\n    # (so DNS cannot rebind between the two), and never follows redirects.\n    try:\n        response = safe_get(\n            url,\n            stream=True,  # Enable streaming for size limiting\n            timeout=(_CONNECT_TIMEOUT, _READ_TIMEOUT),\n        )\n    except requests.exceptions.Timeout:\n        raise ErrorUploadingFile(\n            f\"Request timed out fetching URL: {_sanitize_url_for_logging(url)}\"\n        )\n    except requests.exceptions.RequestException as e:\n        raise ErrorUploadingFile(\n            f\"Failed to fetch file from URL: {_sanitize_url_for_logging(url)}. Error: {e}\"\n        )\n\n    # Reject redirects - require direct URL to resource\n    if response.status_code in (301, 302, 303, 307, 308):\n        location = response.headers.get(\"Location\", \"unknown\")\n        response.close()\n        raise ErrorUploadingFile(\n            f\"URL returned redirect to {_sanitize_url_for_logging(location)}. \"\n            f\"Please provide a direct URL to the file.\"\n        )\n\n    # Check for successful response\n    if not response.ok:","sourceCodeStart":394,"sourceCodeEnd":430,"githubUrl":"https://github.com/ComposioHQ/composio/blob/64b1b85502b1beeb2379e6c9e8bf1104504fa637/python/composio/core/models/_files.py#L394-L430","documentation":"Same duplicate-slug rule as the top-level list, but for tools contributed by toolkits: a toolkit's tool slug collides (case-insensitively) with an already-registered top-level custom tool or a previously processed toolkit's tool.","triggerScenarios":"Passing toolkits to build_custom_tools_map_from_response where tk.tools contains a slug that .upper()-matches a slug already in handles_by_original, via create/use/test_builds_from_response.","commonSituations":"Two toolkits exposing a common base tool name; a toolkit tool sharing a name with a standalone custom tool; shared helper tool modules imported by multiple toolkits.","solutions":["Rename the colliding tool inside the toolkit (or the toolkit prefix scheme)","Remove the standalone tool that duplicates the toolkit one","Namespace tool slugs per toolkit (e.g. GH_CREATE_ISSUE vs JIRA_CREATE_ISSUE)"],"exampleFix":"# before\ntoolkit_a = Toolkit(slug='a', tools=[CustomTool(slug='CREATE', ...)])\ntoolkit_b = Toolkit(slug='b', tools=[CustomTool(slug='create', ...)])\n# after\ntoolkit_a = Toolkit(slug='a', tools=[CustomTool(slug='A_CREATE', ...)])\ntoolkit_b = Toolkit(slug='b', tools=[CustomTool(slug='B_CREATE', ...)])","handlingStrategy":"validation","validationCode":"seen = {h.slug.upper() for h in tools}\nfor tk in toolkits or []:\n    for h in tk.tools:\n        k = h.slug.upper()\n        if k in seen:\n            raise ValueError(f'Slug {h.slug} in toolkit {tk.slug} already registered')\n        seen.add(k)","typeGuard":"def no_cross_toolkit_collisions(tools: list, toolkits: list) -> bool:\n    seen = {h.slug.upper() for h in tools}\n    for tk in toolkits:\n        for h in tk.tools:\n            if h.slug.upper() in seen:\n                return False\n            seen.add(h.slug.upper())\n    return True","tryCatchPattern":"try:\n    m = build_custom_tools_map_from_response(tools, toolkits)\nexcept ValidationError as e:\n    if 'unique slug' in str(e):\n        raise ValueError(f'Toolkit tool collision: {e}') from e\n    raise","preventionTips":["Prefix shared tool names with the toolkit name (GH_FETCH vs SLACK_FETCH)","Keep per-toolkit tool inventories in one place to spot overlaps"],"tags":["python","custom-tools","toolkit","slug","duplicate"],"backgroundTag":"duplicate-identifier","analyzedSha":"64b1b85502b1beeb2379e6c9e8bf1104504fa637","analyzedAt":"2026-08-28T15:39:33.623Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}