From 262b8ee66722f810fcb070226a4250481d4387ec Mon Sep 17 00:00:00 2001 From: mvdbeek Date: Mon, 6 Apr 2026 16:14:13 +0200 Subject: [PATCH] Validate workflow invocation parameters values are dicts The `parameters` field in workflow invocation payloads expects values to be dicts mapping parameter names to values, but this was not enforced by the schema. Passing scalar values (e.g. `{"1": 70}`) caused a TypeError in `_step_parameters` when calling `dict.update()` on a non-dict value. Tighten the Pydantic type from `dict[str, Any]` to `dict[str, dict[str, Any]]` so invalid payloads are rejected with a 400 instead of causing a 500. Fixes https://github.com/galaxyproject/galaxy/issues/22387 --- client/src/api/schema/schema.ts | 4 +++- lib/galaxy/schema/workflows.py | 2 +- lib/galaxy_test/api/test_workflows.py | 9 +++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/client/src/api/schema/schema.ts b/client/src/api/schema/schema.ts index 91c22b3eb39..1abd1423293 100644 --- a/client/src/api/schema/schema.ts +++ b/client/src/api/schema/schema.ts @@ -17056,7 +17056,9 @@ export interface components { * @default {} */ parameters: { - [key: string]: unknown; + [key: string]: { + [key: string]: unknown; + }; } | null; /** * Legacy Step Parameters Normalized diff --git a/lib/galaxy/schema/workflows.py b/lib/galaxy/schema/workflows.py index 0a7399e27b8..0411d554b6e 100644 --- a/lib/galaxy/schema/workflows.py +++ b/lib/galaxy/schema/workflows.py @@ -178,7 +178,7 @@ class InvokeWorkflowPayload(GetTargetHistoryPayload): return json.loads(v) return v - parameters: Optional[dict[str, Any]] = Field( + parameters: Optional[dict[str, dict[str, Any]]] = Field( {}, title=STEP_PARAMETERS_TITLE, description=STEP_PARAMETERS_DESCRIPTION, diff --git a/lib/galaxy_test/api/test_workflows.py b/lib/galaxy_test/api/test_workflows.py index 89417a8f55a..55dbba99934 100644 --- a/lib/galaxy_test/api/test_workflows.py +++ b/lib/galaxy_test/api/test_workflows.py @@ -28,6 +28,7 @@ from galaxy.exceptions import error_codes from galaxy.tool_util_models import UserToolSource from galaxy.util import UNKNOWN from galaxy_test.base import rules_test_data +from galaxy_test.base.api_asserts import assert_error_message_contains from galaxy_test.base.populators import ( DatasetCollectionPopulator, DatasetPopulator, @@ -8231,6 +8232,14 @@ steps: self.__assert_lines_hid_line_count_is(history_id, 2, 5) self.__assert_lines_hid_line_count_is(history_id, 3, 5) + @skip_without_tool("random_lines1") + def test_run_replace_params_by_tool_rejects_scalar_values(self): + workflow_request, history_id, workflow_id = self._setup_random_x2_workflow("test_for_reject_scalar_params") + workflow_request["parameters"] = dumps(dict(random_lines1=5)) + response = self.workflow_populator.invoke_workflow_raw(workflow_id, workflow_request) + self._assert_status_code_is(response, 400) + assert_error_message_contains(response, "Input should be a valid dictionary") + @skip_without_tool("random_lines1") def test_run_replace_params_by_uuid(self): workflow_request, history_id, workflow_id = self._setup_random_x2_workflow("test_for_replace_")