Repository: apache/airflow
File: airflow-ctl/src/airflowctl/api/operations.py (Python)

Code before:
            trigger_dag_run.conf = {}
        try:
            self.response = self.client.post(
                f"dags/{dag_id}/dagRuns", json=trigger_dag_run.model_dump(mode="json")
            )
            return DAGRunResponse.model_validate_json(self.response.content)
        except ServerResponseError as e:
            raise e


class DagRunOperations(BaseOperations):
    """Dag run operations."""

    def get(self, dag_id: str, dag_run_id: str) -> DAGRunResponse | ServerResponseError:
        """Get a dag run."""
        try:
            self.response = self.client.get(f"/dags/{dag_id}/dagRuns/{dag_run_id}")
            return DAGRunResponse.model_validate_json(self.response.content)
        except ServerResponseError as e:
            raise e

    def list(
        self,
        start_date: datetime.datetime | None = None,
        end_date: datetime.datetime | None = None,
        state: str | None = None,
        limit: int | None = None,
        dag_id: str | None = None,
    ) -> DAGRunCollectionResponse | ServerResponseError:
        """
        List all dag runs.

        Args:
            start_date: Filter dag runs by start date (optional)
            end_date: Filter dag runs by end date (optional)
            state: Filter dag runs by state (optional)
            limit: Limit the number of results (optional)
            dag_id: The DAG ID to filter by. If None, retrieves dag runs for all DAGs (using "~").
        """
        # Use "~" for all DAGs if dag_id is not specified
        if not dag_id:
            dag_id = "~"

        params: dict[str, object] = {}
        if start_date is not None:
            params["start_date"] = start_date
        if end_date is not None:
            params["end_date"] = end_date
        if state is not None:
            params["state"] = state
        if limit is not None:

Review comment (suggestion):
https://github.com/apache/airflow/blob/327201f5f9198ab3d19c1a07b8a39bcd0f61a7c4/airflow-core/src/airflow/api_fastapi/core_api/datamodels/dag_run.py#L79
Unfortunately, some fields cannot be `None` due to the API side of it. We can follow the same approach as how you set a default variable for them. Could you please double-check with the datamodel? I think some can indeed, such as end_date, but some canno,t such as state

Code after:
            trigger_dag_run.conf = {}
        try:
            self.response = self.client.post(
                f"dags/{dag_id}/dagRuns", json=trigger_dag_run.model_dump(mode="json")
            )
            return DAGRunResponse.model_validate_json(self.response.content)
        except ServerResponseError as e:
            raise e


class DagRunOperations(BaseOperations):
    """Dag run operations."""

    def get(self, dag_id: str, dag_run_id: str) -> DAGRunResponse | ServerResponseError:
        """Get a dag run."""
        try:
            self.response = self.client.get(f"/dags/{dag_id}/dagRuns/{dag_run_id}")
            return DAGRunResponse.model_validate_json(self.response.content)
        except ServerResponseError as e:
            raise e

    def list(
        self,
        state: str,
        limit: int,
        start_date: datetime.datetime | None = None,
        end_date: datetime.datetime | None = None,
        dag_id: str | None = None,
    ) -> DAGRunCollectionResponse | ServerResponseError:
        """
        List all dag runs.

        Args:
            state: Filter dag runs by state
            start_date: Filter dag runs by start date (optional)
            end_date: Filter dag runs by end date (optional)
            state: Filter dag runs by state
            limit: Limit the number of results
            dag_id: The DAG ID to filter by. If None, retrieves dag runs for all DAGs (using "~").
        """
        # Use "~" for all DAGs if dag_id is not specified
        if not dag_id:
            dag_id = "~"

        params: dict[str, object] = {
            "state": state,
            "limit": limit,
        }
        if start_date is not None:
            params["start_date"] = start_date
        if end_date is not None: