ComposioHQ/composio · error · ErrorUploadingFile
Failed to fetch file from URL: {_sanitize_url_for_logging(ur
Error message
Failed to fetch file from URL: {_sanitize_url_for_logging(url)}. Error: {e} What it means
The legacy top-level preload mechanism received a string instead of a list. preload.tools must be a list of Composio tool slugs or the literal 'all'; custom tools are preloaded by setting preload=True on the tool/toolkit definition, not via preload.tools.
Source
Thrown at python/composio/core/models/_files.py:416
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:
response.close()
raise ErrorUploadingFile(
f"Failed to fetch file from URL: {_sanitize_url_for_logging(url)}. "
f"Status: {response.status_code}"View on GitHub (pinned to 64b1b85502)
Solutions
- Wrap the slug in a list: preload=['my_tool']
- Use the literal 'all' (PRELOAD_TOOLS_ALL) only if you truly want everything
- Set preload=True on the CustomTool/Toolkit definition instead of using top-level preload for custom tools
Example fix
# before composio.use(toolkits=['github'], preload_tools='GITHUB_CREATE_ISSUE') # after composio.use(toolkits=['github'], preload_tools=['GITHUB_CREATE_ISSUE'])
Defensive patterns
Strategy: type-guard
Validate before calling
if isinstance(preload_tools, str):
preload_tools = [preload_tools] if preload_tools != 'all' else 'all'
composio.use(toolkits=toolkits, preload_tools=preload_tools) Type guard
def is_valid_preload(value) -> bool:
if value is None or value == 'all':
return True
return isinstance(value, list) and all(isinstance(s, str) for s in value) Try / catch
try:
composio.use(toolkits=toolkits, preload_tools=preload)
except ValidationError as e:
if 'preload.tools must be a list' in str(e):
composio.use(toolkits=toolkits, preload_tools=[preload])
else:
raise Prevention
- Always pass preload.tools as a list of slugs or the literal 'all'
- Use preload=True on custom tool/toolkit definitions instead of top-level preload for custom tools
When it happens
Trigger: Passing preload_tools='my_tool' (a bare string) to the SDK path that calls assert_no_custom_tool_slugs_in_preload via _prepare_inline_custom_tools, e.g. composio.use(..., preload={'tools': 'SOME_TOOL'}) or an equivalent string preload argument.
Common situations: Migrating from an older API that accepted a single slug string; writing preload='all' in lowercase or a single slug where a list was expected; copy-pasting a slug where a list belongs.
Understand the failure class
Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.
Related errors
- URL returned redirect to {_sanitize_url_for_logging(location
- Could not determine a home directory to store the Composio c
- Cache directory {directory} is not writable please provide a
- module {__name__!r} has no attribute {name!r}
- 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/054a8b338575b5ae.
Report an issue: GitHub.