<@ULVA73B9P> One of my flows has a parameter of ty...
# ask-marvin
n
@Marvin One of my flows has a parameter of type pendulum.Date. When running the flow locally it works, but when deployed it fails validation
Input should be an instance of Date
. The UI properly shows a date picker.
m
thought for 438.5 seconds
Thanks for the details — this is a classic parameters/validation mismatch. What’s happening - Locally, you’re likely calling the flow with an actual
pendulum.Date
instance, so validation passes. - In a deployment, the UI serializes inputs over the API (JSON). Pydantic (used by Prefect 3.x for parameter validation) can parse strings into built-in
datetime.date
, but it does not know how to parse into
pendulum.Date
unless you provide custom validators. For arbitrary/custom classes, Pydantic generally expects an instance to already be of that type. Hence the error “Input should be an instance of Date.” Recommended fix - Annotate your parameter as a standard
datetime.date
(or
datetime.datetime
), then convert to Pendulum inside the flow if you need it. Example
Copy code
from datetime import date
import pendulum
from prefect import flow

@flow
def my_flow(run_date: date):
    # Convert if you need a Pendulum date
    p_date = pendulum.date(run_date.year, run_date.month, run_date.day)
    ...
If you must keep a Pendulum type - Wrap the parameter in a Pydantic model with a validator that parses strings into
pendulum.Date
, and allow arbitrary types. Note: this will present as an object in the UI instead of a single date field.
Copy code
from datetime import date as pydate
import pendulum
from pydantic import BaseModel, ConfigDict, field_validator
from prefect import flow

class Params(BaseModel):
    model_config = ConfigDict(arbitrary_types_allowed=True)
    run_date: pendulum.Date

    @field_validator("run_date", mode="before")
    def parse_run_date(cls, v):
        if isinstance(v, str):
            # Accept ISO strings from the UI
            return pendulum.parse(v).date()
        if isinstance(v, pydate):
            return pendulum.date(v.year, v.month, v.day)
        return v

@flow
def my_flow(params: Params):
    p_date = params.run_date
    ...
Why this is the case - Prefect 3.x validates flow parameters using Pydantic. Values sent from the UI/API are JSON-encoded; Pydantic has built-in parsing for stdlib datetime/date, but not for
pendulum.Date
without custom validators. See source references: - Flows and parameter handling: prefect/src/prefect/flows.py - Serialization helpers: prefect/src/prefect/serializers.py If you share your flow signature and how you’re invoking it locally vs. in the UI, I can confirm the minimal change. But in most cases, switching the annotation to
datetime.date
and converting to Pendulum inside the flow is the simplest and most reliable approach.