diff --git a/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParameterAddPanel.tsx b/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParameterAddPanel.tsx index ad686a61..76ebc9d3 100644 --- a/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParameterAddPanel.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParameterAddPanel.tsx @@ -61,6 +61,7 @@ function WorkflowParameterAddPanel({ type, onClose, onSave }: Props) { const reservedKeys = ["current_item", "current_value", "current_index"]; const isCloud = useContext(CloudContext); const [key, setKey] = useState(""); + const hasWhitespace = /\s/.test(key); const [urlParameterKey, setUrlParameterKey] = useState(""); const [description, setDescription] = useState(""); const [bitwardenCollectionId, setBitwardenCollectionId] = useState(""); @@ -108,6 +109,11 @@ function WorkflowParameterAddPanel({ type, onClose, onSave }: Props) {
setKey(e.target.value)} /> + {hasWhitespace && ( +

+ Spaces are not allowed, consider using _ +

+ )}
@@ -398,6 +404,14 @@ function WorkflowParameterAddPanel({ type, onClose, onSave }: Props) { }); return; } + if (hasWhitespace) { + toast({ + variant: "destructive", + title: "Failed to add parameter", + description: "Key cannot contain whitespaces", + }); + return; + } if (reservedKeys.includes(key)) { toast({ variant: "destructive", diff --git a/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParameterEditPanel.tsx b/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParameterEditPanel.tsx index 0034cc20..0d636ac4 100644 --- a/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParameterEditPanel.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParameterEditPanel.tsx @@ -73,6 +73,7 @@ function WorkflowParameterEditPanel({ }: Props) { const isCloud = useContext(CloudContext); const [key, setKey] = useState(initialValues.key); + const hasWhitespace = /\s/.test(key); const isBitwardenCredential = initialValues.parameterType === "credential" && parameterIsBitwardenCredential(initialValues); @@ -192,6 +193,11 @@ function WorkflowParameterEditPanel({
setKey(e.target.value)} /> + {hasWhitespace && ( +

+ Spaces are not allowed, consider using _ +

+ )}
@@ -480,6 +486,15 @@ function WorkflowParameterEditPanel({ }); return; } + if (hasWhitespace) { + toast({ + variant: "destructive", + title: "Failed to save parameter", + description: + "Key cannot contain whitespace characters. Consider using underscores (_) instead.", + }); + return; + } if (type === "workflow") { if ( parameterType === "json" && diff --git a/skyvern/schemas/workflows.py b/skyvern/schemas/workflows.py index 8d95c6f0..1c6b0a56 100644 --- a/skyvern/schemas/workflows.py +++ b/skyvern/schemas/workflows.py @@ -3,7 +3,7 @@ from dataclasses import dataclass from enum import StrEnum from typing import Annotated, Any, Literal -from pydantic import BaseModel, Field +from pydantic import BaseModel, Field, field_validator from skyvern.config import settings from skyvern.forge.sdk.workflow.models.parameter import OutputParameter, ParameterType, WorkflowParameterType @@ -74,6 +74,13 @@ class ParameterYAML(BaseModel, abc.ABC): key: str description: str | None = None + @field_validator("key") + @classmethod + def validate_no_whitespace(cls, v: str) -> str: + if any(char in v for char in [" ", "\t", "\n", "\r"]): + raise ValueError("Key cannot contain whitespaces") + return v + class AWSSecretParameterYAML(ParameterYAML): # There is a mypy bug with Literal. Without the type: ignore, mypy will raise an error: