ansible/ansible · error · AnsibleError

Invalid non absolute download_url: {data["download_url"]}

Error message

Invalid non absolute download_url: {data["download_url"]}

What it means

Raised in the CollectionVersionMetadata construction path (get_collection_version_metadata) when a Galaxy server returns a version payload whose 'download_url' has neither a scheme nor a path starting with '/'. Because _call_galaxy cannot return the final redirected URL, a relative URL that is not root-relative cannot be reliably joined onto api_server, so ansible refuses it rather than download from a wrong URL.

Source

Thrown at lib/ansible/galaxy/api.py:795

        n_collection_url = _urljoin(*url_paths)
        error_context_msg = 'Error when getting collection version metadata for %s.%s:%s from %s (%s)' \
                            % (namespace, name, version, self.name, self.api_server)
        data = self._call_galaxy(n_collection_url, error_context_msg=error_context_msg, cache=True)
        self._set_cache()

        signatures = data.get('signatures') or []

        # NOTE: Galaxy and Hub already populated the cache when listing versions.
        # NOTE: Allow 3rd party servers to provide version-specific metadata lazily.
        if (requires_ansible := data.get('requires_ansible')):
            self.requires_ansible[f"{namespace}.{name}"][version] = requires_ansible

        download_url_info = urlparse(data['download_url'])
        if not download_url_info.scheme and not download_url_info.path.startswith('/'):
            # galaxy does a lot of redirects, with much more complex pathing than we use
            # within this codebase, without updating _call_galaxy to be able to return
            # the final URL, we can't reliably build a relative URL.
            raise AnsibleError(f'Invalid non absolute download_url: {data["download_url"]}')

        download_url = urljoin(self.api_server, data['download_url'])

        return CollectionVersionMetadata(data['namespace']['name'], data['collection']['name'], data['version'],
                                         download_url, data['artifact']['sha256'],
                                         data['metadata']['dependencies'], data['href'], signatures)

    @g_connect(['v3'])
    def get_collection_versions(self, namespace, name):
        """
        Gets a list of available versions for a collection on a Galaxy server.

        :param namespace: The collection namespace.
        :param name: The collection name.
        :return: A list of versions that are available.
        """
        api_path = self.available_api_versions['v3']
        pagination_path = ['links', 'next']

View on GitHub (pinned to 9cf16a4aca)

Solutions

  1. Fix the server (or its reverse proxy) to return an absolute URL or a root-relative path ('/api/v2/...') in download_url
  2. Update galaxy_ng to a version that conforms to the published API contract
  3. As a workaround, download the tarball manually and 'ansible-galaxy collection install <tarball>'
  4. If a proxy rewrites URLs, disable that rewrite for the Galaxy API paths
Defensive patterns

Strategy: validation

Validate before calling

from urllib.parse import urlparse

def server_download_urls_look_valid(sample_version_payload):
    u = urlparse(sample_version_payload['download_url'])
    return bool(u.scheme) or u.path.startswith('/')

Prevention

When it happens

Trigger: Installing a collection from a 3rd-party Galaxy-compatible server whose API returns a relative download_url like 'download/xyz' (no leading slash and no scheme). Standard galaxy.ansible.com and automation hub return absolute URLs, so this almost always indicates a nonconforming or misconfigured proxy/galaxy_ng deployment.

Common situations: Custom in-house Galaxy implementations; reverse proxies that rewrite Location/download URLs and strip the leading slash; installing from a requirements.yml pointing at such a server via -s/--server.

Related errors


AI-assisted analysis of ansible/ansible@9cf16a4aca (2026-08-15). Data as JSON: /api/errors/9a42458d24791460. Report an issue: GitHub.