odysseus-dev/odysseus · error · SkillImportError

unsupported URL scheme: {scheme}

Error message

unsupported URL scheme: {scheme}

What it means

Raised by parse_skill_source (services/memory/skill_importer.py) when the URL carries an explicit scheme:// form whose scheme is neither http nor https — e.g. file://, ftp://, ssh://, javascript:, or a non-web scheme. The guard distinguishes real schemes from urlparse artifacts (schemeless 'host:port' or opaque schemes), and only the true scheme:// shape raises this specific error; unsupported hosts in other shapes get the host-based message instead.

Source

Thrown at services/memory/skill_importer.py:278

            continue
        return r
    raise SkillImportError("too many redirects while fetching skill bundle")


def parse_skill_source(url: str) -> ResolvedSource:
    """Normalize skills.sh / GitHub web URLs into owner/repo/ref/path."""
    url = (url or "").strip()
    if not url:
        raise SkillImportError("URL is required")

    # ``urlparse`` only reports an unambiguous scheme when the URL carries the
    # ``scheme://`` form. Opaque schemes (``mailto:``, ``javascript:``) and a
    # schemeless ``host:port`` both parse a "scheme" that is not one, so they
    # fall through to the host check below and are rejected on the host instead.
    scheme = urlparse(url).scheme.lower()
    if scheme not in ("http", "https"):
        if scheme and url.lower().startswith(f"{scheme}://"):
            raise SkillImportError(f"unsupported URL scheme: {scheme}")
        # Schemeless "github.com/owner/repo" — accept only a supported host.
        rough_host = (urlparse("//" + url).hostname or "").lower()
        if rough_host not in _GITHUB_HOSTS and rough_host not in _SKILLS_SH_HOSTS:
            raise SkillImportError("Only GitHub or skills.sh URLs are supported")
        url = "https://" + url

    parsed = urlparse(url)
    hostname = (parsed.hostname or "").lower()
    if hostname not in _GITHUB_HOSTS and hostname not in _SKILLS_SH_HOSTS:
        raise SkillImportError("Only GitHub or skills.sh URLs are supported")

    # A skills.sh link is only usable if it redirects to an exact supported
    # GitHub host. Scraping the page body for a github.com link cannot work:
    # skill pages only ever link the repository root, never the skill's
    # subdirectory, so the scrape resolves every skill in a repo to the same
    # (wrong) bundle. Fail with an actionable message instead.
    if hostname in _SKILLS_SH_HOSTS:
        r = _get_checked(url, timeout=20.0)

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. Use an https:// GitHub web URL: https://github.com/<owner>/<repo>/tree/<ref>/<skill-path>.
  2. Convert SSH remotes to HTTPS: git@github.com:owner/repo.git → https://github.com/owner/repo.
  3. For a local skill, do not use file:// — push it to a GitHub repo first or copy it into the skills directory manually if your tooling allows.
  4. Fix typo'd schemes (htps:// → https://).

Example fix

# before
import_skill("file:///Users/me/skills/foo")
SkillImportError: unsupported URL scheme: file

# after
import_skill("https://github.com/me/repo/tree/main/skills/foo")
Defensive patterns

Strategy: validation

Validate before calling

from urllib.parse import urlparse

def assert_http_url(url: str) -> None:
    scheme = urlparse(url.strip()).scheme.lower()
    if scheme not in ('http', 'https', ''):  # '' = schemeless host/path, handled by host check
        raise ValueError(f'unsupported scheme {scheme!r}; use https://github.com/...')

Type guard

def is_http_or_schemeless(url: str) -> bool:
    return urlparse(url.strip()).scheme.lower() in ('http', 'https', '')

Try / catch

try:
    src = parse_skill_source(url)
except SkillImportError as e:
    if 'unsupported URL scheme' in str(e):
        # convert common SSH/remote forms to https
        url = url.replace('git@github.com:', 'https://github.com/').removesuffix('.git')
        src = parse_skill_source(url)
    else:
        raise

Prevention

When it happens

Trigger: Importing a skill from file:///Users/me/skills/foo; git@github.com:owner/repo.git style SSH URLs misparsed as a scheme; ftp:// or http+insecure:// URLs; users pasting a javascript: or data: string; any pasted URL with a typo'd scheme like htps:// that urlparse still treats as a scheme when followed by //.

Common situations: Users pasting the SSH clone URL instead of the HTTPS web URL; trying to import a locally cloned skill via file://; CI passing a git-remote-style URL where a browser URL is expected.

Related errors


AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14). Data as JSON: /api/errors/8c4f78ef8c259b05. Report an issue: GitHub.