<@ULVA73B9P> how can i provide optional kwargs to ...
# ask-marvin
o
@Marvin how can i provide optional kwargs to a prefect flow? i tried @flow() def flow_fun( instrument_ids: list[int] | None = None, n_random: Optional[int] = None, iterations: int = 3, db_type: Literal['sqlite', 'duckdb'] = 'duckdb', **kwargs ) -> Dict[str, object]: return other_fun( db_type=db_type, intraday=True, iterations=iterations, **kwargs) but when i then try to run it in prefect ui I get "'kwargs' is a required property"
m
thought for 160.3 seconds
Short answer: Prefect 3.x does not support
*kwargs
in a flow’s signature. The UI builds a form from the flow’s parameter schema, and
*kwargs
cannot be represented there—hence the “‘kwargs’ is a required property” error. Use one of these patterns instead: 1) Single dict for extras - Define a dict parameter and expand it when calling downstream functions.
Copy code
from typing import Any, Literal

from prefect import flow

@flow
def flow_fun(
    instrument_ids: list[int] | None = None,
    n_random: int | None = None,
    iterations: int = 3,
    db_type: Literal["sqlite", "duckdb"] = "duckdb",
    extra: dict[str, Any] | None = None,
) -> dict[str, Any]:
    extra = extra or {}
    return other_fun(db_type=db_type, intraday=True, iterations=iterations, **extra)
- In the UI, you can pass:
Copy code
{
  "instrument_ids": [
    1,
    2,
    3
  ],
  "iterations": 5,
  "db_type": "duckdb",
  "extra": {
    "foo": "bar",
    "limit": 10
  }
}
2) Pydantic model for structured/validated extras - If you want typed/validated extras and a nicer UI form, wrap them in a model.
Copy code
from typing import Any, Literal
from pydantic import BaseModel, Field
from prefect import flow

class ExtraOpts(BaseModel):
    intraday: bool = True
    limit: int | None = None
    mode: Literal["fast", "full"] = "full"
    arbitrary: dict[str, Any] = Field(default_factory=dict)

@flow
def flow_fun(
    instrument_ids: list[int] | None = None,
    n_random: int | None = None,
    iterations: int = 3,
    db_type: Literal["sqlite", "duckdb"] = "duckdb",
    opts: ExtraOpts = Field(default_factory=ExtraOpts),
) -> dict[str, Any]:
    return other_fun(
        db_type=db_type,
        intraday=opts.intraday,
        iterations=iterations,
        **opts.arbitrary,
    )
- The UI will render fields for
opts
and you can still carry arbitrary extras via
opts.arbitrary
. Notes: - Disabling parameter validation won’t fix
**kwargs
in the UI; the UI still needs a concrete schema. - If you ever need to read all passed parameters inside a flow, you can access them via
get_run_context().flow_run.parameters
, but you still need a concrete signature for the UI. Docs for more detail: - Flows and parameters - Form building and parameter schemas If you share what you’re trying to forward via
**kwargs
, I can suggest a concrete model or dict shape that will work cleanly in the UI.