crewAIInc/crewAI · error · ValueError
url is required either in constructor or method call
Error message
url is required either in constructor or method call
What it means
Raised by BrightDataUnlockerTool._run when the url parameter is falsy after fallback (url = url or self.url). The unlocker fetches exactly one page per call, and its payload is built around that URL, so no default or inference exists.
Source
Thrown at lib/crewai-tools/src/crewai_tools/tools/brightdata_tool/brightdata_unlocker.py:118
self.zone = os.getenv("BRIGHT_DATA_ZONE") or ""
if not self.api_key:
raise ValueError("BRIGHT_DATA_API_KEY environment variable is required.")
if not self.zone:
raise ValueError("BRIGHT_DATA_ZONE environment variable is required.")
def _run(
self,
url: str | None = None,
format: str | None = None,
data_format: str | None = None,
**kwargs: Any,
) -> Any:
url = url or self.url
format = format or self.format
data_format = data_format or self.data_format
if not url:
raise ValueError("url is required either in constructor or method call")
payload = {
"url": url,
"zone": self.zone,
"format": format,
}
valid_data_formats = {"html", "markdown"}
if data_format not in valid_data_formats:
raise ValueError(
f"Unsupported data format: {data_format}. Must be one of {', '.join(valid_data_formats)}."
)
if data_format == "markdown":
payload["data_format"] = "markdown"
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json",View on GitHub (pinned to 754d7323be)
Solutions
- Pass the URL per call: tool.run(url='https://example.com/pricing').
- Or bind it in the constructor: BrightDataUnlockerTool(url='https://example.com/pricing').
- Ensure the value is a non-empty http(s) URL string.
Example fix
# before result = tool.run(data_format='markdown') # ValueError: url is required # after result = tool.run(url='https://example.com/pricing', data_format='markdown')
Defensive patterns
Strategy: validation
Validate before calling
def validate_unlock_url(url: str | None) -> str:
if not url or not url.startswith(("http://", "https://")):
raise ValueError("A fully qualified URL is required for BrightDataUnlockerTool")
return url
result = tool.run(url=validate_unlock_url(url), data_format='markdown') Type guard
def is_unlocker_call_ready(kwargs: dict, tool) -> bool:
return bool(kwargs.get("url") or tool.url) Try / catch
try:
result = tool.run(data_format='markdown')
except ValueError as e:
if "url is required" in str(e):
result = tool.run(url=get_url_from_context(), data_format='markdown')
else:
raise Prevention
- Bind url in the constructor for single-page targets; validate per-call URLs otherwise.
- Reject empty strings from prompt/agent interpolation before tool dispatch.
- Remember the unlocker fetches exactly one page per call — there is no batch mode.
When it happens
Trigger: Constructing BrightDataUnlockerTool() with no url and calling tool.run(format='markdown'); passing url=None/'' at both constructor and call; agents omitting the url argument.
Common situations: Tool instantiated generically for reuse with the URL expected per call but forgotten, empty URL from prompt interpolation, config templates leaving url blank.
Related errors
- url is required either in constructor or method call
- dataset_type is required either in constructor or method cal
- query is required either in constructor or method call
- Unsupported data format: {data_format}. Must be one of {', '
- Invalid URL scheme: {self.url}
AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15).
Data as JSON: /api/errors/fbe0ed7c4f7adca8.
Report an issue: GitHub.