Fugo Takefusa
11/06/2025, 2:11 AMMarvin
11/06/2025, 2:11 AMMarvin
11/06/2025, 2:15 AMprefect.concurrency._asyncio does not export concurrency anymore. Even if you don’t import it yourself, Prefect (or an extension/old deployment image) can import it internally, which triggers this ImportError.
Most common causes
- Mixed versions across components: e.g., you upgraded Prefect locally but your worker/Docker image still runs an older build (or vice versa).
- A third‑party integration or old project code still referencing the private path prefect.concurrency._asyncio.
- A deployment or cached environment built with an older Prefect version being run with a newer version.
What to do
1) Verify versions are consistent everywhere:
python -c "import prefect, sys; print('prefect', prefect.__version__, '| python', sys.version)"
prefect version
If you use workers/containers, run the same checks inside those environments. Make sure they all run the same latest 3.x.
2) If you do import concurrency anywhere, use the public API in 3.x:
from prefect.concurrency.asyncio import concurrency
3) Rebuild/redeploy:
- Reinstall Prefect to latest 3.x in every environment.
- Rebuild any worker/Docker images and restart workers so they pick up the new version.
- If you pinned Prefect to 2.x anywhere, either upgrade to 3.x across the board or pin everything consistently to the same 2.x version.
References
- Global concurrency limits (Prefect 3.x)
- Task runners (execution model)
Could you share:
- Your Prefect version and Python version
- How you’re running the flow (local, worker, Docker/Kubernetes image)
- Whether you recently upgraded from 2.x to 3.x
That will let me confirm which component is pulling in the old private import and give you an exact fix.Nate
11/06/2025, 2:59 AMFugo Takefusa
11/06/2025, 3:29 AMNate
11/06/2025, 4:52 AMprefect-dbt installation might have (depending on how it was installed) clobbered your base image's prefect site-packages and then ended in a state that referenced the old concurrency code. ill check to see if there's a lower bound to bump in prefect-dbt to help avoid situations like this (@Marvin wanna sanity check my assessment?)Marvin
11/06/2025, 4:52 AMMarvin
11/06/2025, 4:55 AMprefect-dbt in the runtime either:
- Pulled in an older Prefect (2.x) due to its version constraints and downgraded/clobbered the base image’s prefect, or
- Left behind stale files during an upgrade/downgrade (e.g., a private prefect/concurrency/_asyncio.py) that no longer match the rest of the package.
Both can lead to imports pointing at the old private _asyncio module path and failing in 3.x.
Sanity checks
- Verify what actually got installed in the runtime:
- pip show prefect prefect-dbt
- python -c "import prefect, sys; print(prefect.__version__, sys.version)"
- Inspect the on-disk layout: python -c "import prefect, os; import prefect.concurrency as c; print(os.listdir(os.path.dirname(c.__file__)))"
- If you see both _asyncio.py and an asyncio/ package, you’ve got residue.
- Clean reinstall in the runtime to fix residue/mismatch:
- pip install --upgrade --force-reinstall --no-cache-dir "prefect>=3,<4"
- Then install a Prefect‑3‑compatible prefect-dbt and re-run.
Package constraints recommendation
- In prefect-dbt, if the current release is 3.x‑compatible, set a lower bound on Prefect to avoid resolver downgrades: e.g. prefect>=3,<4.
- If you still support Prefect 2.x with older prefect-dbt releases, keep those pinned with prefect<3 so users don’t mix them accidentally.
- Add a brief install note in the README: “Use prefect>=3,<4 with `prefect-dbt >= <X.Y>`” to prevent cross‑major collisions.
Related docs
- Global concurrency limits (Prefect 3.x)
- prefect-dbt integration docs
If you can share which prefect-dbt version triggered this and how it was installed (pip/uv/conda; Docker layer order), I can double-check the exact constraint you might want to bump.