xtekky/gpt4free · error · ValueError

url must be a non-empty string

Error message

url must be a non-empty string

What it means

Thrown by MarkItDown.convert_url() when url is None, not a str, or a whitespace-only string. It is the input-contract check run before the scheme check; anything that is not a non-empty string is rejected without any network attempt.

Source

Thrown at g4f/integration/markitdown/__init__.py:237

        )
        if m:
            owner, repo, ref, path = (m.group(1), m.group(2), m.group(3), m.group(4))
            # Strip a trailing slash if any
            path = path.rstrip("/")
            return f"https://raw.githubusercontent.com/{owner}/{repo}/{ref}/{path}"

        # Tree (directory) URLs and repo roots: cannot map to a single raw file
        return url

    def convert_url(
        self,
        url: str,
        *,
        stream_info: Optional[StreamInfo] = None,
        **kwargs: Any,
    ) -> DocumentConverterResult:
        if url is None or not isinstance(url, str) or url.strip() == "":
            raise ValueError("url must be a non-empty string")
        if not url.startswith(("http://", "https://")):
            raise ValueError("url must start with http:// or https://")
        if url.startswith("https://github.com/"):
            # Special case for GitHub URLs -- convert to raw content URL
            url = self._convert_github_url_to_raw(url)
        return super().convert_url(url, stream_info=stream_info, **kwargs)

View on GitHub (pinned to 973504e177)

Solutions

  1. Validate before calling: if not isinstance(url, str) or not url.strip(): raise/handle.
  2. Default missing config values: url = config.get('url') or '' and skip empty ones.
  3. When iterating, unpack: for url in urls: md.convert_url(url) rather than passing the list.

Example fix

// before
result = md.convert_url(payload.get("source_url"))  # None when key missing

// after
url = payload.get("source_url")
if not isinstance(url, str) or not url.strip():
    raise ValueError("source_url missing")
result = md.convert_url(url)
Defensive patterns

Strategy: type-guard

Validate before calling

def valid_url_arg(url) -> bool:
    return isinstance(url, str) and url.strip() != ''

Type guard

def is_non_empty_str(url: unknown) -> bool:
    return typeof url === 'string' && url.trim().length > 0
# Python:
def is_non_empty_str(url) -> bool:
    return isinstance(url, str) and bool(url.strip())

Try / catch

try:
    md.convert_url(url)
except ValueError as e:
    if "non-empty string" in str(e):
        return None  # skip bad record
    raise

Prevention

When it happens

Trigger: convert_url(None); convert_url(123); convert_url(' '); convert_url(['https://a']) (a list/tuple instead of a single string).

Common situations: Passing a value read from JSON/config where the key was missing (None); passing a urllib.parse result object instead of .geturl(); forgetting to unpack a list of URLs before looping.

Related errors


AI-assisted analysis of xtekky/gpt4free@973504e177 (2026-08-14). Data as JSON: /api/errors/cf59f8ebc47c6143. Report an issue: GitHub.