Skip to content

Python Workers: ModuleNotFoundError: No module named 'workers' on deploy, even with official pywrangler init scaffold #212

Closed

Description

@swiercnas-hash

What versions & operating system are you using?

System:
OS: Windows 10 10.0.19045
CPU: Intel Core i5-4300U
Binaries:
Node: 24.18.0
npm: 11.16.0
npmPackages (worker project):
wrangler: 4.123.0
workers-py: 1.16.4
workers-runtime-sdk: 1.6.13

Please provide a link to a minimal reproduction

No hosted repo needed - reproduces with the official scaffold itself: uvx --from workers-py pywrangler init myapp --accept-defaults --no-deploy --no-git --no-open then cd myapp && uv run pywrangler deploy (unmodified generated entry.py/pyproject.toml/wrangler.jsonc).

Describe the Bug

Deploying any Python Worker fails at the Cloudflare API validation step with a ModuleNotFoundError for the 'workers' package - even the entry.py generated by the official scaffold.

Steps to reproduce:

  1. uvx --from workers-py pywrangler init myapp --accept-defaults --no-deploy --no-git --no-open
    1. cd myapp
    1. uv run pywrangler deploy
      Expected: deploy succeeds with the unmodified generated template.
      Actual: fails with the error pasted below. The traceback shows it originates from Cloudflare's own internal introspection.py trying from workers import (...), not from user code - the generated entry.py's own from workers import Response, WorkerEntrypoint line is where it dies.

I also tried a hand-written minimal Worker (single file, async def on_fetch(request, env) + js.Response.new(...), zero dependencies, wrangler.toml with only compatibility_flags = ["python_workers"]) via plain wrangler deploy - identical error.

Things I tried that did not fix it:

  • compatibility_flags: ["python_workers", "disable_python_external_sdk"] - gets past this specific error, but then fails differently with "The uploaded script has no registered event handlers" [code: 10068].
    • Upgrading wrangler 4.112.0 -> 4.123.0 - no change.
      • Empty requirements.txt, and requirements.txt containing just "workers" - no change (this was before I found the pywrangler/pyproject.toml flow; same error persists with that flow too).
        Account is on the Workers Free plan, if relevant.

Please provide any relevant error logs

X [ERROR] A request to the Cloudflare API (/accounts/.../workers/scripts/myapp/versions) failed.

Uncaught Error: PythonError: Traceback (most recent call last):
File "/lib/python313.zip/_pyodide/_base.py", line 523, in eval_code
.run(globals, locals)
~~~^^^^^^^^^^^^^^^^^
File "/lib/python313.zip/_pyodide/_base.py", line 357, in run
coroutine = eval(self.code, globals, locals)
File "", line 9, in
File "/lib/python313.zip/_pyodide/_base.py", line 666, in pyimport_impl
res = import(stem, fromlist=fromlist)
File "/session/metadata/entry.py", line 10, in
from workers import Response, WorkerEntrypoint
File "/lib/python3.13/site-packages/workers/init.py", line 3, in
raise err
ModuleNotFoundError: No module named 'workers'
You need to update to workers-py >= 1.90 or to pass disable_python_external_sdk

at null.<anonymous> (pyodideRuntime-internal:emscriptenSetup:19919:14) in new_error
at [object Object] in $wrap_exception
at [object Object] in $pythonexc2js
at null.<anonymous> (pyodideRuntime-internal:emscriptenSetup:22411:37) in callPyObjectKwargs
at null.<anonymous> (pyodideRuntime-internal:emscriptenSetup:23309:20) in callKwargs
at null.<anonymous> (pyodideRuntime-internal:emscriptenSetup:24469:87) in runPython
at null.<anonymous> (pyodide:python-entrypoint-helper:73:17) in handleSrcImport
at null.<anonymous> (pyodide:python-entrypoint-helper:190:17)

[code: 10021]

Activity

  1. workers-devprod commented on Aug 15, 2026

    @workers-devprod
    Contributor

    Note

    This is an automated, advisory triage report generated by workers-devprod. It is not an official maintainer response — a maintainer will follow up.

    🤖 Automated triage report

    Issue Triage: #212

    Summary

    Deploying any Python Worker — including the unmodified official pywrangler init scaffold — fails at the Cloudflare API validation/introspection step with ModuleNotFoundError: No module named 'workers'.

    Classification

    • Type: Bug
    • Component: packages/wrangler (Python Workers deploy path; python label). Root cause likely in the workers-py / workers-runtime-sdk packaging (repo: cloudflare/workers-py).
    • Severity: High
    • Has Reproduction: Yes (self-contained steps against the official scaffold; no external repo needed)
    • Quality: Complete

    Findings

    • Created: 2026-08-15
    • Author: swiercnas-hash
    • Version: wrangler 4.123.0, workers-py 1.16.4, workers-runtime-sdk 1.6.13 (Node 24.18.0, npm 11.16.0, Windows 10)
    • Labels: python
    • Comments: 4 (2 automated triage bot comments, 1 detailed reporter follow-up, 1 confirmation from a second user)

    Analysis

    • Reproducible and well-scoped. The reporter gives exact copy-pasteable steps using the official scaffold with unmodified generated files (uvx --from workers-py pywrangler init ... && uv run pywrangler deploy). They also reproduced it with a hand-written zero-dependency Worker via plain wrangler deploy — identical error. The failure is in the scaffold's own entry.py line from workers import Response, WorkerEntrypoint, before any user code.
    • Independently confirmed. A second user (waylan) reports the identical error and traceback on Windows 11 for a brand-new project, also on workers-py==1.16.4. This rules out a one-off account/state problem and points to a real, shared defect.
    • Error message is self-contradictory / suggests a version-parse bug. The runtime error says "You need to update to workers-py >= 1.90", yet both affected users are on 1.16.4. 1.16.4 is newer than 1.90 under semver, so a naive string/float comparison of the version (treating 1.16 as < 1.9) would explain why the guard fires incorrectly. waylan explicitly notes Version comparison bug: workers-py >= 1.90 requirement blocks upgrade from 1.9.3 #120 covered only the 1.9.0 vs 1.90 message typo, not the underlying logic.
    • No clean workaround. Adding disable_python_external_sdk gets past the ModuleNotFoundError but then fails with "The uploaded script has no registered event handlers" [code: 10068]. Deleting and redeploying a fresh script, empty requirements.txt, and requirements.txt containing workers all reproduce the same error. Upgrading wrangler 4.112.0 → 4.123.0 made no difference.
    • Triage bot could not reproduce — but only on a temporary account. The auto-triage repro succeeded via --temporary (unauthenticated throwaway account). The reporter shows --temporary is rejected once authenticated, and hits the error every time on their real Free-plan account. The temporary-vs-authenticated difference may be a meaningful variable (e.g. plan tier, SDK-injection path) and should be checked when reproducing.

    Recommendation

    Status: NEEDS VERIFICATION

    Reasoning: This is a complete, independently-confirmed bug that blocks the officially documented Python Workers deploy path, with no clean workaround and no fix from upgrading. The one automated repro that "passed" used a temporary account, so it does not disprove the report; a maintainer needs to reproduce on a real authenticated account and pinpoint whether the fix belongs in wrangler's Python deploy/introspection path or in the workers-py / workers-runtime-sdk packaging.

    Action: Route to a maintainer with Python Workers context. Reproduce on a real authenticated account (not --temporary), ideally on the Workers Free plan and on Windows, following the reporter's exact steps. Investigate the workers-py >= 1.90 version check for a string/float version-comparison bug that misfires for 1.16.x. If the root cause is in the SDK packaging, transfer to / open a companion issue in cloudflare/workers-py; keep this open until confirmed.

    Suggested Labels: python

    Suggested Comment

    Thanks for the very thorough write-up, and for the follow-up timeline — reproducing this against the unmodified pywrangler init scaffold, plus the second confirmation from @waylan on Windows 11, is really helpful.

    One detail stands out: the error says "update to workers-py >= 1.90", but you're both on 1.16.4, which is already newer than 1.90. That looks like it could be a version-comparison bug (treating 1.16 as lower than 1.9), so the SDK guard fires when it shouldn't. We'll dig into that.

    A couple of things that would help us narrow it down:

    • Can either of you reproduce on macOS or Linux, or does it only happen on Windows?
    • Does it still fail if you pin workers-py to an earlier version (e.g. 1.9.x)?

    Note that the earlier automated repro succeeded on a temporary (unauthenticated) account, which behaves differently from an authenticated one, so it doesn't rule out what you're seeing. We'll reproduce on a real account and follow up. If it turns out the fix belongs in the Python SDK, we'll track it in cloudflare/workers-py.

    Structured summary (JSON)
    {
      "issueNumber": 15208,
      "title": "Python Workers: ModuleNotFoundError: No module named 'workers' on deploy, even with official pywrangler init scaffold",
      "githubUrl": "https://github.com/cloudflare/workers-py/issues/212",
      "recommendation": "NEEDS VERIFICATION",
      "difficulty": "medium",
      "reasoning": "Complete, independently-confirmed bug blocking the official Python Workers deploy path, with no clean workaround and unaffected by upgrading; the only 'passing' repro used a temporary account so it needs verification on a real authenticated account. The 'update to workers-py >= 1.90' message misfiring for 1.16.4 suggests a version-comparison bug.",
      "suggestedAction": "Route to a Python Workers maintainer to reproduce on a real authenticated account (not --temporary), investigate the workers-py >= 1.90 version-comparison guard for a string/float bug misfiring on 1.16.x, and determine whether the fix belongs in wrangler's deploy path or in the workers-py/workers-runtime-sdk packaging (cloudflare/workers-py).",
      "hasSuggestedComment": true,
      "suggestedLabels": ["python"]
    }
    
  2. workers-devprod commented on Aug 15, 2026

    @workers-devprod
    Contributor
    • Reproduction: ❌ Could not reproduce. Official scaffold with workers-py 1.16.4 deployed successfully to a temporary Cloudflare account using uv run pywrangler deploy --temporary. Worker responded correctly to requests, rather than failing with the reported ModuleNotFoundError during API validation.
  3. swiercnas-hash commented on Aug 15, 2026

    @swiercnas-hash
    Author

    Thanks for the triage! A couple of things worth noting since this happens consistently and I've been able to narrow it down a bit further:

    Timeline of what I tried, in order, all on the same real (non-temporary) authenticated account, Workers Free plan:

    1. Hand-written single-file Worker (async def on_fetch(request, env), zero deps, plain wrangler deploy) -> ModuleNotFoundError.
      1. Same, with compatibility_flags: ["python_workers", "disable_python_external_sdk"] added -> gets past the import, fails differently with "no registered event handlers" [code: 10068].
      1. Reverted to just ["python_workers"], added empty requirements.txt -> same ModuleNotFoundError as wrangler dev workers-sdk#1.
      1. requirements.txt containing just workers -> same ModuleNotFoundError as wrangler dev workers-sdk#1.
      1. Switched to the official flow: uvx --from workers-py pywrangler init scaffold, pyproject.toml with workers-py/workers-runtime-sdk dev deps, class-based Default(WorkerEntrypoint), deployed via uv run pywrangler deploy -> same ModuleNotFoundError, now failing on the scaffold's own entry.py line from workers import Response, WorkerEntrypoint (not even my code yet).
      1. uv run pywrangler deploy --temporary -> rejected: "You're already authenticated with Cloudflare, so --temporary can't be used."
      1. Deleted the Worker entirely (wrangler delete) and deployed fresh (brand new script, no prior deploy history) -> identical ModuleNotFoundError, same traceback.
        So it's not stale/corrupted state on a specific Worker - a brand new script hits it too, on this account, every time, regardless of which of the two documented workarounds I try. Given the bot's repro attempt succeeded on a temporary (unauthenticated, throwaway) account rather than a real authenticated one, and step 6 shows --temporary is unavailable once authenticated, I can't currently produce a passing case on my own account to compare against. If it'd help, happy to share the account ID privately or run any diagnostic command a maintainer suggests.
  4. waylan commented on Aug 17, 2026

    @waylan

    I'm getting the same error in the same circumstances. The only difference is that I am on Windows 11 rather than WIndows 10. This is a new install for a new project and deploy always results in the same error.

    X [ERROR] service core:user:dingus: Uncaught Error: PythonError: Traceback (most recent call last):
    
        File "/lib/python313.zip/_pyodide/_base.py", line 523, in eval_code
          .run(globals, locals)
           ~~~^^^^^^^^^^^^^^^^^
        File "/lib/python313.zip/_pyodide/_base.py", line 357, in run
          coroutine = eval(self.code, globals, locals)
        File "<exec>", line 9, in <module>
        File "/lib/python313.zip/_pyodide/_base.py", line 666, in pyimport_impl
          res = __import__(stem, fromlist=fromlist)
        File "/session/metadata/entry.py", line 1, in <module>
          from workers import Response, WorkerEntrypoint
        File "/lib/python3.13/site-packages/workers/__init__.py", line 3, in <module>
          raise err
      ModuleNotFoundError: No module named 'workers'
      You need to update to workers-py >= 1.90 or to pass disable_python_external_sdk
    
        at null.<anonymous> (pyodideRuntime-internal:emscriptenSetup:19919:14) in new_error
        at [object Object] in $wrap_exception
        at [object Object] in $pythonexc2js
        at null.<anonymous> (pyodideRuntime-internal:emscriptenSetup:22411:37) in callPyObjectKwargs
        at null.<anonymous> (pyodideRuntime-internal:emscriptenSetup:23309:20) in callKwargs
        at null.<anonymous> (pyodideRuntime-internal:emscriptenSetup:24469:87) in runPython
        at null.<anonymous> (pyodide:python-entrypoint-helper:73:17) in handleSrcImport
        at null.<anonymous> (pyodide:python-entrypoint-helper:190:17)
    

    For completeness, I did find #120, but that seems to be about a typo in the error message (1.9.0 instead of 1.90), not the code. As I and the original reporter both have workers-py==1.16.4, we should be well beyond that issue.

  5. dom96 commented on Aug 18, 2026

    @dom96
    Contributor

    async def on_fetch(request, env)

    requirements.txt

    This is not related to this bug, but just for future reference, the above are no longer supported. You should be using pywrangler + pyproject.toml to get the packages you need into your worker, and you should be using class Default(WorkerEntrypoint): def fetch(..): ... for your handlers.

  6. moved this from Untriaged to Other in workers-sdkon Aug 18, 2026
  7. ryanking13 commented on Aug 19, 2026

    @ryanking13
    Contributor

    Closing as resolved by #214. Please let us know if the error still persists after updating workers-py to the latest version.

  8. waylan commented on Aug 19, 2026

    @waylan

    That resolves the issue for me. Thank you,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions