Troubleshooting¶
The errors below are the ones a first Dag most often hits. Each names the message you see, the cause, and the fix.
Model and connection errors¶
No model specified for connection '...'The connection has no
modelin its extra and the operator did not passmodel_id. Set the Model field on the connection (provider:modelform) or passmodel_idto the operator. See Pydantic AI connection.Connection '...' has no default model provider, so the bare model name '...' cannot be resolvedThe generic
pydanticaiconnection type needs aprovider:prefix on the model name, for exampleopenai:gpt-5rather thangpt-5. Add the prefix, or use a vendor connection type (Pydantic AI (Azure OpenAI) connection, Pydantic AI (AWS Bedrock) connection, Pydantic AI (Google Vertex AI) connection), which supply their own platform.'...' is not a provider pydantic-ai recognizesThe text before the first
:in the model name is not a pydantic-ai provider. Check it for a typo. If the vendor’s own model id contains a:(Bedrock-style version suffixes, for example), use the matching vendor connection type instead of the generic one.- An
ImportErrorforpydantic_ai.models.<vendor>, the vendor SDK, orpydantic_ai_harness The provider is installed without the extra for that vendor, or without
code-modeforpydantic_ai_harness. Install it, quoting the package name so the brackets survive the shell:pip install "apache-airflow-providers-common-ai[openai]"
Installation lists the extras.
A fallback chain is configured for '...' but no model is setfallback_conn_idson the connection needs an explicit primary model. Set the Model field on the primary connection ormodel_idon the operator. A model taken from an agent spec file cannot be wrapped in a fallback chain. See Provider fallback.Fallback connection '...' resolves to ..., which is not a PydanticAIHookEvery entry in
fallback_conn_idsmust be one of thepydanticaiconnection types. Chains are also not resolved recursively, so a fallback connection may not declare its ownfallback_conn_ids; list every vendor directly on the primary.Connection '...' has type '...', but a Pydantic AI hook needs one of [...]The connection named by
llm_conn_idis not apydanticaiconnection type. This is easy to hit by picking a similarly named type such asopenaiwhen the OpenAI provider is installed. Change the connection type topydanticai, put the API key in the API Key field (the password) and the model, for exampleopenai:gpt-5, in Model. For Azure, Bedrock or Vertex use the matchingpydanticai_azure,pydanticai_bedrockorpydanticai_vertextype instead; see Supported model providers.
- A connection of type
pydanticai-azure,pydanticai-bedrockorpydanticai-vertexno longer resolves These connection types are spelled with an underscore:
pydanticai_azure,pydanticai_bedrockandpydanticai_vertex.Connections stored as a URI or as JSON need no change:
-is how_is encoded in a URI scheme, so the hyphenated form is decoded to the underscore form on read. That coversAIRFLOW_CONN_*environment variables and secrets backends such as HashiCorp Vault, AWS Secrets Manager and GCP Secret Manager.A connection whose type is stored verbatim does need updating, because the hyphen is preserved and no longer matches a registered hook. That means rows in the metadata database, including any created through the UI, and connections imported in object form from a local file:
airflow connections get <conn_id> -o json # confirm conn_type is 'pydanticai-azure' airflow connections delete <conn_id> airflow connections add <conn_id> --conn-type pydanticai_azure ...
In the UI, edit the connection and re-pick its type.
Operator construction errors¶
These raise while the Dag file is parsed, so the whole file fails to import. A mapped
task (.expand()) is constructed at run time instead, so there the same error surfaces
as a task failure.
require_approval=True needs Airflow 3.1+/DecisionPolicy(on_uncertain='review') needs Airflow 3.1+/approval_assigned_users needs Airflow 3.1+/Human in the loop functionality needs Airflow 3.1+Human-in-the-loop review, whether through
require_approval,DecisionPolicy(on_uncertain="review")orenable_hitl_review, needs Airflow 3.1 or later. Upgrade Airflow, or useon_uncertain="fail"and drop the review flags on an older Airflow version. See Approval gates for LLM operators and Human-in-the-loop (HITL) review for agents.durable=True and enable_hitl_review=True cannot be used togetherDurable replay matches each step to the one at the same position in the previous attempt, which a human review loop’s regenerations do not keep. Pick one. See Durable execution.
durable=True needs a unique id on every FunctionToolset, such as FunctionToolset(..., id='orders')Durable replay records each tool call under its toolset’s id, so a
FunctionToolset,MCPToolsetorDynamicToolsetwithout one is refused when the Dag loads. Setid=on the toolset itself; an id on aToolsetcapability around it does not reach it. See Durable execution.durable=True attaches AirflowDurability itself; pass durable=True or the capability, not both.AgentOperator(durable=True)adds the capability to the agent, so a second one incapabilitieswould record every step twice. Drop one of them.message_history and enable_hitl_review=True cannot be used togetherThe post-review transcript is not recoverable today, so the operator refuses rather than silently dropping the reviewed turns. See Multi-turn sessions and message history.
... does not support decision_policy yetOnly
LLMOperatorandLLMBranchOperatorhonor aDecisionPolicywith a confidence bar. The SQL, schema-compare and file-analysis operators run their ownexecuteand reject one at construction; userequire_approval=Truethere for an unconditional review.on_approval_timeout=... needs a review path ... and a positive approval_timeout to fireon_approval_timeoutother than"fail"only makes sense when a review can open (require_approval=Trueor a reviewingdecision_policy) andapproval_timeoutis set to a positivetimedelta. Set both or leave the default.
Run-time errors¶
An agent needs to have a model in order to be used with Airflow, it cannot be set at agent run time.The agent was built without a model, usually because the connection has no
modeland nomodel_idwas passed. Durable execution needs the model resolved up front so that replayed steps can be matched against their fingerprints. Fix the connection as described above.DurableJournalError: durable execution could not record a step's result, because it is not JSON-serializableA tool returned a value that cannot be encoded as JSON. The model could not have read it either, so the task fails without retrying. Return text, numbers, lists, dicts or a Pydantic model. See Durable execution.
durable=Trueon Airflow below 3.3 fails with aValueErroraboutdurable_cache_pathOn Airflow versions older than 3.3 the step cache lives in object storage and
[common.ai] durable_cache_pathmust be set. On 3.3 and later the task state store is used and the option is ignored. See Durable execution.- A structured
output_typearrives downstream as a string or fails to deserialize The Pydantic class must be defined at module scope under its own
__name__so the worker can register it for XCom deserialization, and a consumer in a different Dag needs the class added to[core] allowed_deserialization_classes. Passserialize_output=Trueto receive a plaindictinstead. See Structured output and XCom.- A review task waits for a long time
That is expected: the task is waiting for a reviewer. An approval gate on an LLM operator releases its worker slot while it waits (it pauses as awaiting input on Airflow 3.3+, and defers to the triggerer on older Airflow versions); a HITL review on
AgentOperatorpolls from the worker and holds its slot. Setapproval_timeoutorhitl_timeoutso an unattended review cannot wait forever. See Approval gates for LLM operators and Human-in-the-loop (HITL) review for agents.- The provider returns a rate limit or is down
Three features answer this at different layers. Airflow’s own
retriesre-run the task. Provider fallback fails over to another vendor inside one attempt. Retry policies lets a model classify the failure and decide whether a retry is worth it. They compose; each page says where it sits among the others.
Still stuck¶
Every operator logs a post-run summary with the model name, token usage and the tool
call sequence, and AgentOperator logs each tool call as it happens. Turn the task
log level to DEBUG to see tool arguments and the model output. Observability (OpenTelemetry tracing)
covers exporting the same information as OpenTelemetry traces.