diff --git a/lib/galaxy/tool_source_store/populator.py b/lib/galaxy/tool_source_store/populator.py index b0bcfe9f401..2f99545406a 100644 --- a/lib/galaxy/tool_source_store/populator.py +++ b/lib/galaxy/tool_source_store/populator.py @@ -60,6 +60,7 @@ from galaxy.tool_source_store.index import ( ToolIndexEntry, ) from galaxy.tool_util.parser import get_tool_source +from galaxy.tool_util.parser.util import parse_tool_version_with_defaults from galaxy.tool_util.toolbox.parser import get_toolbox_parser log = logging.getLogger(__name__) @@ -435,10 +436,20 @@ def build_index_entry_from_source( except Exception: pass + # Honour the same version-default rules as ``Tool.__init__``: empty + # ``version`` on a pre-16.04-profile tool becomes "1.0.0"; on newer + # profiles it raises. Without this, ``ToolLineage.register_version`` + # crashes on ``Version(None)`` during the eager walk. + try: + version = parse_tool_version_with_defaults(tool_id, tool_source) + except Exception as e: + log.warning("parse_tool_version_with_defaults raised for %s: %s", tool_id, e) + version = tool_source.parse_version() or "0" + return ToolIndexEntry( id=tool_id, uuid=uuid_val, - version=tool_source.parse_version(), + version=version, name=tool_source.parse_name() or "", description=tool_source.parse_description() or "", panel_section_id=discovered.section_id, diff --git a/lib/galaxy/tools/lazy_toolbox.py b/lib/galaxy/tools/lazy_toolbox.py index f8ec4fac0f9..435fc9abaf9 100644 --- a/lib/galaxy/tools/lazy_toolbox.py +++ b/lib/galaxy/tools/lazy_toolbox.py @@ -249,13 +249,22 @@ class LazyTool: def to_dict(self, trans=None, link_details: bool = False, tool_help: bool = False, **kw) -> dict[str, Any]: """API serialisation. ``link_details=False`` stays on the entry fast path. - ``link_details=True`` (used by ``/api/tools//build``) needs the full - :meth:`Tool.to_dict` payload (parameters, citations, ...). That triggers - materialise. The default and EDAM panel listings call with - ``link_details=False`` and stay cheap. + ``link_details=True`` (used by ``/api/tools//build`` and the panel + view walk) needs the full :meth:`Tool.to_dict` payload (parameters, + citations, ...). That triggers materialise. If materialise raises + (tool XML with options/filters the parser can't handle — + ``upload_dataset``, ``column="value"`` against an unresolvable + column-name spec, …), fall back to the entry-only fast-path dict so + the panel listing still renders. The eager toolbox catches the same + errors at boot in ``_load_tool_tag_set`` and drops the tool from + ``_tools_by_id``; we surface them lazily and degrade gracefully + instead. """ if link_details: - return self._materialize().to_dict(trans, link_details=True, tool_help=tool_help, **kw) + try: + return self._materialize().to_dict(trans, link_details=True, tool_help=tool_help, **kw) + except Exception as e: + log.warning("LazyTool.to_dict: materialise failed for %s, falling back to entry: %s", self.id, e) entry = self._entry return { "id": self.id,