Repository: apache/airflow
File: airflow-core/src/airflow/ui/src/queries/useTrigger.ts (TypeScript)

Code before:
    ];

    await Promise.all(queryKeys.map((key) => queryClient.invalidateQueries({ queryKey: key })));

    toaster.create({
      description: translate("triggerDag.toaster.success.description"),
      title: translate("triggerDag.toaster.success.title"),
      type: "success",
    });
    onSuccessConfirm();

    // Only redirect if we're already on the dag page
    if (selectedDagId === dagRun.dag_id) {
      navigate(`/dags/${dagRun.dag_id}/runs/${dagRun.dag_run_id}`);
    }
  };

  const onError = (_error: Error) => {
    // Check if error is a 403 (Forbidden) status
    if (isHttpError(_error, 403)) {
      toaster.create({
        description: _error.message,
        title: translate("triggerDag.toaster.error.forbidden.title", "Trigger DAG Permission Denied"),
        type: "error",
      });
    } else {
      // Generic error handling for other status codes
      toaster.create({
        description: _error.message,
        title: translate("triggerDag.toaster.error.generic.title", "Failed to Trigger DAG"),
        type: "error",
      });
    }
    setError(_error);
  };

  const { isPending, mutate } = useDagRunServiceTriggerDagRun({
    onError,
    onSuccess,
  });

  const triggerDagRun = (dagRunRequestBody: DagRunTriggerParams) => {
    const parsedConfig = JSON.parse(dagRunRequestBody.conf) as Record<string, unknown>;

    const logicalDate = dagRunRequestBody.logicalDate ? new Date(dagRunRequestBody.logicalDate) : undefined;

    // eslint-disable-next-line unicorn/no-null
    const formattedLogicalDate = logicalDate?.toISOString() ?? null;

    const checkDagRunId = dagRunRequestBody.dagRunId === "" ? undefined : dagRunRequestBody.dagRunId;
    const checkNote = dagRunRequestBody.note === "" ? undefined : dagRunRequestBody.note;

Review comment (suggestion):
You don't need this first case. 

Just show the second case always that can handle any type of backend error, and display the error.

Basically we need something similar to `useDeleteVariable`, a generic:
```
  const onError = (error: Error) => {
    toaster.create({
      description: error.message,
      title: translate("toaster.delete.error", {
        resourceName: translate("admin:variables.variable_one"),
      }),
      type: "error",
    });
  };
```

Code after:

    await Promise.all(queryKeys.map((key) => queryClient.invalidateQueries({ queryKey: key })));

    toaster.create({
      description: translate("triggerDag.toaster.success.description"),
      title: translate("triggerDag.toaster.success.title"),
      type: "success",
    });
    onSuccessConfirm();

    // Only redirect if we're already on the dag page
    if (selectedDagId === dagRun.dag_id) {
      navigate(`/dags/${dagRun.dag_id}/runs/${dagRun.dag_run_id}`);
    }
  };

  const onError = (_error: Error) => {
    toaster.create({
      description: _error.message,
      title: translate("triggerDag.toaster.error.title"),
      type: "error",
    });
    setError(_error);
  };

  const { isPending, mutate } = useDagRunServiceTriggerDagRun({
    onError,
    onSuccess,
  });

  const triggerDagRun = (dagRunRequestBody: DagRunTriggerParams) => {
    const parsedConfig = JSON.parse(dagRunRequestBody.conf) as Record<string, unknown>;

    const logicalDate = dagRunRequestBody.logicalDate ? new Date(dagRunRequestBody.logicalDate) : undefined;

    // eslint-disable-next-line unicorn/no-null
    const formattedLogicalDate = logicalDate?.toISOString() ?? null;

    const checkDagRunId = dagRunRequestBody.dagRunId === "" ? undefined : dagRunRequestBody.dagRunId;
    const checkNote = dagRunRequestBody.note === "" ? undefined : dagRunRequestBody.note;

    mutate({
      dagId,
      requestBody: {
        conf: parsedConfig,
        dag_run_id: checkDagRunId,
        logical_date: formattedLogicalDate,
        note: checkNote,
        partition_key: dagRunRequestBody.partitionKey ?? null,
      },
    });