{"record":{"id":"32ee2c85022f1e44","repo":"ansible/ansible","slug":"invalid-version-found-for-the-collection-first-r","errorCode":null,"errorMessage":"Invalid version found for the collection '{first_req}'. {version_req}","messagePattern":"Invalid version found for the collection '(.+?)'\\. (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"lib/ansible/galaxy/dependency_resolution/providers.py","lineNumber":239,"sourceCode":"\n        # If we're upgrading collections, we can't calculate preinstalled_candidates until the latest matches are found.\n        # Otherwise, we can potentially avoid a Galaxy API call by doing this first.\n        preinstalled_candidates = set()\n        if not self._upgrade and first_req.type == 'galaxy':\n            preinstalled_candidates = {\n                candidate for candidate in self._preferred_candidates\n                if candidate.fqcn == fqcn and\n                all(self.is_satisfied_by(requirement, candidate) for requirement in requirements)\n            }\n        try:\n            coll_versions: _c.Iterable[tuple[str, GalaxyAPI]] = (\n                [] if preinstalled_candidates\n                else self._api_proxy.get_collection_versions(first_req)\n            )\n        except TypeError as exc:\n            if first_req.is_concrete_artifact:\n                # Non hashable versions will cause a TypeError\n                raise ValueError(\n                    f\"Invalid version found for the collection '{first_req}'. {version_req}\"\n                ) from exc\n            # Unexpected error from a Galaxy server\n            raise\n\n        if first_req.is_concrete_artifact:\n            # FIXME: do we assume that all the following artifacts are also concrete?\n            # FIXME: does using fqcn==None cause us problems here?\n\n            # Ensure the version found in the concrete artifact is SemVer-compliant\n            for version, req_src in coll_versions:\n                version_err = f\"Invalid version found for the collection '{first_req}': {version} ({type(version)}). {version_req}\"\n                # NOTE: The known cases causing the version to be a non-string object come from\n                # NOTE: the differences in how the YAML parser normalizes ambiguous values and\n                # NOTE: how the end-users sometimes expect them to be parsed. Unless the users\n                # NOTE: explicitly use the double quotes of one of the multiline string syntaxes\n                # NOTE: in the collection metadata file, PyYAML will parse a value containing\n                # NOTE: two dot-separated integers as `float`, a single integer as `int`, and 3+","sourceCodeStart":221,"sourceCodeEnd":257,"githubUrl":"https://github.com/ansible/ansible/blob/9cf16a4aca7898481c257f1e17ad28d0b67b1f85/lib/ansible/galaxy/dependency_resolution/providers.py#L221-L257","documentation":"Raised in CollectionDependencyProvider._find_matches (lib/ansible/galaxy/dependency_resolution/providers.py) when get_collection_versions() raises TypeError for a concrete artifact requirement (local tarball/dir/git URL). For concrete artifacts, versions come from the artifact's own MANIFEST/galaxy metadata; a non-hashable version value there bubbles up as TypeError, which is converted to this ValueError with the SemVer guidance text.","triggerScenarios":"Installing a requirements entry that is a concrete artifact (type file/dir/git/url) whose embedded version string is malformed enough that internal version handling raises TypeError during version enumeration — e.g. an unhashable type produced by broken metadata.","commonSituations":"Hand-crafted or tool-generated tarballs with corrupt MANIFEST.json; collections built by old/buggy builders producing non-string versions; artifacts whose metadata was edited after build.","solutions":["Inspect the artifact's MANIFEST.json `collection_info.version` and make it a quoted SemVer string like \"1.0.0\"","Rebuild the artifact with a current ansible-dev-tools/ansible-galaxy build instead of editing metadata by hand","If from a git URL, ensure the checked-out tree has a valid galaxy.yml version","Replace the broken artifact with one from Galaxy that passes verification"],"exampleFix":"# MANIFEST.json before\n\"collection_info\": { \"version\": 1.0 }\n\n# after\n\"collection_info\": { \"version\": \"1.0.0\" }","handlingStrategy":"try-catch","validationCode":"import json\n\ndef precheck_artifact_version(manifest_path):\n    info = json.load(open(manifest_path))['collection_info']\n    v = info.get('version')\n    if not isinstance(v, str):\n        raise SystemExit(f'MANIFEST.json version must be a quoted string, got {type(v).__name__}: {v!r}')","typeGuard":null,"tryCatchPattern":"try:\n    ansible_galaxy_install(artifact_req)\nexcept ValueError as e:\n    if 'Invalid version found for the collection' in str(e):\n        fail_with_hint('fix artifact metadata version to SemVer \"X.Y.Z\" and rebuild')\n    raise","preventionTips":["Rebuild artifacts with ansible-galaxy collection build rather than editing MANIFEST.json","Validate MANIFEST.json collection_info.version is a quoted SemVer string in CI before publishing"],"tags":["semver","collections","metadata","concrete-artifact"],"backgroundTag":null,"analyzedSha":"9cf16a4aca7898481c257f1e17ad28d0b67b1f85","analyzedAt":"2026-08-15T00:15:47.100Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}