Repository: PrefectHQ/prefect

Issue:
Can't pass parameters to a Clock unless they have default values
## Description
*A clear description of the bug*
I would like to create a flow on a schedule, passing in default parameters. Currently this fails unless all parameters have default values.



## Expected Behavior
*What did you expect to happen instead?*
Passing parameters should be allowed even if they do not have defaults - we should be able to resolve the following example

## Reproduction
*A minimal example that exhibits the behavior.*
```from prefect import task, Parameter, Flow

from prefect.schedules import Schedule
from prefect.schedules.clocks import CronClock


@task
def add(a, b):
    return a + b


schedule = Schedule(clocks=[
    CronClock(
        cron=f"* * * * *",
        parameter_defaults={
            'a': 1,
        }
    )
])

with Flow('flow', schedule=schedule) as flow:
    a = Parameter('a')
    b = Parameter('b', default=1)
    result = add(a, b)

flow.register()
```

## Environment
*Any additional information about your environment*

*Optionally run `prefect diagnostics` from the command line and paste the information here*



Discussion:

Resolving patch:
diff --git a/server/src/prefect_server/api/flows.py b/server/src/prefect_server/api/flows.py
--- a/server/src/prefect_server/api/flows.py
+++ b/server/src/prefect_server/api/flows.py
@@ -83,8 +83,17 @@ async def create_flow(
         f = prefect.serialization.flow.FlowSchema().load(copy.deepcopy(serialized_flow))
     except Exception as exc:
         raise ValueError(f"Invalid flow: {exc}")
-    if f.schedule and any([p.required for p in f.parameters()]):
-        raise ValueError("Can not schedule a flow that has required parameters.")
+    required_parameters = [p for p in f.parameters() if p.required]
+    if f.schedule is not None and required_parameters:
+        required_names = {p.name for p in required_parameters}
+        if not all(
+            [
+                required_names <= set(c.parameter_defaults.keys())
+                for c in f.schedule.clocks
+            ]
+        ):
+            raise ValueError("Can not schedule a flow that has required parameters.")
+
     # set up task detail info
     reference_tasks = f.reference_tasks()
     root_tasks = f.root_tasks()
diff --git a/src/prefect/client/client.py b/src/prefect/client/client.py
--- a/src/prefect/client/client.py
+++ b/src/prefect/client/client.py
@@ -551,7 +551,7 @@ def register(
             required_names = {p.name for p in required_parameters}
             if not all(
                 [
-                    required_names == set(c.parameter_defaults.keys())
+                    required_names <= set(c.parameter_defaults.keys())
                     for c in flow.schedule.clocks
                 ]
             ):


Test patch:
diff --git a/server/tests/api/test_flows.py b/server/tests/api/test_flows.py
--- a/server/tests/api/test_flows.py
+++ b/server/tests/api/test_flows.py
@@ -222,6 +222,18 @@ async def test_create_flow_assigns_description(self, flow):
         flow = await m.Flow.where(id=flow_id).first("description")
         assert flow.description == description
 
+    async def test_create_flow_intelligently_handles_scheduled_param_defaults(self):
+        a, b = prefect.Parameter("a"), prefect.Parameter("b", default=1)
+        clock = prefect.schedules.clocks.CronClock(
+            cron=f"* * * * *", parameter_defaults={"a": 1, "b": 2}
+        )
+        schedule = prefect.schedules.Schedule(clocks=[clock])
+
+        flow = prefect.Flow("test-params", tasks=[a, b], schedule=schedule)
+
+        flow_id = await flows.create_flow(serialized_flow=flow.serialize())
+        assert flow_id
+
     async def test_create_flow_persists_serialized_flow(self, flow):
         flow_id = await flows.create_flow(serialized_flow=flow.serialize())
 
diff --git a/tests/client/test_client.py b/tests/client/test_client.py
--- a/tests/client/test_client.py
+++ b/tests/client/test_client.py
@@ -161,13 +161,14 @@ def test_client_register_doesnt_raise_for_scheduled_params(
         [pendulum.now("UTC").add(seconds=0.1)], parameter_defaults=dict(x=1)
     )
     b = prefect.schedules.clocks.DatesClock(
-        [pendulum.now("UTC").add(seconds=0.25)], parameter_defaults=dict(x=2)
+        [pendulum.now("UTC").add(seconds=0.25)], parameter_defaults=dict(x=2, y=5)
     )
 
     x = prefect.Parameter("x", required=True)
+    y = prefect.Parameter("y", default=1)
 
     flow = prefect.Flow(
-        "test", schedule=prefect.schedules.Schedule(clocks=[a, b]), tasks=[x]
+        "test", schedule=prefect.schedules.Schedule(clocks=[a, b]), tasks=[x, y]
     )
     flow.storage = prefect.environments.storage.Memory()
     flow.result_handler = flow.storage.result_handler