ComposioHQ/composio · error · ErrorUploadingFile
Request timed out fetching URL: {_sanitize_url_for_logging(u
Error message
Request timed out fetching URL: {_sanitize_url_for_logging(url)} What it means
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.
Source
Thrown at python/composio/core/models/_files.py:412
max_size: Maximum response size in bytes (default: 100MB)
Returns:
Tuple of (filename, content_bytes, mimetype)
Raises:
ResponseTooLargeError: If response exceeds max_size
ErrorUploadingFile: If fetch fails for other reasons
"""
# `safe_get` validates the target, connects to the address it validated
# (so DNS cannot rebind between the two), and never follows redirects.
try:
response = safe_get(
url,
stream=True, # Enable streaming for size limiting
timeout=(_CONNECT_TIMEOUT, _READ_TIMEOUT),
)
except requests.exceptions.Timeout:
raise ErrorUploadingFile(
f"Request timed out fetching URL: {_sanitize_url_for_logging(url)}"
)
except requests.exceptions.RequestException as e:
raise ErrorUploadingFile(
f"Failed to fetch file from URL: {_sanitize_url_for_logging(url)}. Error: {e}"
)
# Reject redirects - require direct URL to resource
if response.status_code in (301, 302, 303, 307, 308):
location = response.headers.get("Location", "unknown")
response.close()
raise ErrorUploadingFile(
f"URL returned redirect to {_sanitize_url_for_logging(location)}. "
f"Please provide a direct URL to the file."
)
# Check for successful response
if not response.ok:View on GitHub (pinned to 64b1b85502)
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)
Example fix
# before toolkit_a = Toolkit(slug='a', tools=[CustomTool(slug='CREATE', ...)]) toolkit_b = Toolkit(slug='b', tools=[CustomTool(slug='create', ...)]) # after toolkit_a = Toolkit(slug='a', tools=[CustomTool(slug='A_CREATE', ...)]) toolkit_b = Toolkit(slug='b', tools=[CustomTool(slug='B_CREATE', ...)])
Defensive patterns
Strategy: validation
Validate before calling
seen = {h.slug.upper() for h in tools}
for tk in toolkits or []:
for h in tk.tools:
k = h.slug.upper()
if k in seen:
raise ValueError(f'Slug {h.slug} in toolkit {tk.slug} already registered')
seen.add(k) Type guard
def no_cross_toolkit_collisions(tools: list, toolkits: list) -> bool:
seen = {h.slug.upper() for h in tools}
for tk in toolkits:
for h in tk.tools:
if h.slug.upper() in seen:
return False
seen.add(h.slug.upper())
return True Try / catch
try:
m = build_custom_tools_map_from_response(tools, toolkits)
except ValidationError as e:
if 'unique slug' in str(e):
raise ValueError(f'Toolkit tool collision: {e}') from e
raise Prevention
- Prefix shared tool names with the toolkit name (GH_FETCH vs SLACK_FETCH)
- Keep per-toolkit tool inventories in one place to spot overlaps
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- module {__name__!r} has no attribute {name!r}
- Failed to upload to S3. Status: {response.status_code}. This
- Could not determine a home directory to store the Composio c
- Cache directory {directory} is not writable please provide a
- Failed to upload to S3: {_sanitize_url_for_logging(url)}. Er
AI-assisted analysis of ComposioHQ/composio@64b1b85502 (2026-08-28).
Data as JSON: /api/errors/3128d4d81c26c481.
Report an issue: GitHub.