You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
On Windows, the Python 3.13 proxy worker can exit with 0xC0000005 during indexing/logging after dependency isolation evicts Protobuf modules while retaining worker-generated RPC message classes. Reimporting the samegoogle._upb._message binary and then accessing a retained generated type is sufficient to reproduce a native access violation. Different Protobuf versions, A2A, Durable, gRPC, and the Functions host are not required for the smallest reproduction.
Originally investigated through Azure/azure-functions-agents-runtime#211. The application's earlier physical-versus-editable packaging explanation was superseded by controlled reproductions. This issue tracks the worker/native-module lifetime defect, not an A2A implementation bug.
Still reproducible in the actual host bundled with Core Tools 4.14.0, using an empty Python 3.13 venv without customer Protobuf. Upgrading does improve a different dependency-resolution path; see below.
Environment and release chain
Component
Original
Latest Core Tools comparison (2026-09-09)
Core Tools
4.10.0
4.14.0
Host
4.1048.200.26180
4.1052.200.26352
Proxy worker
4.43.0
4.45.1
V2 library worker
1.1.0
1.1.1
Python
3.13.15, Windows x64
Same
Bundled Protobuf for Python 3.13
5.29.6
5.29.6
Bundled azure-functions for Python 3.13
1.25.0b3
2.2.0b5
The host versions' eng/build/Workers.Python.props specify the worker releases. Because that package reference excludes Windows, the actual downloaded Windows Core Tools distribution and startup logs were also inspected. Worker 4.46.0 is a separate release, not the worker bundled in Core Tools 4.14.0; a 4.46.0 host comparison has not been performed.
Observed failure chain
The proxy worker imports its own Protobuf runtime and proxy_worker.protos, retaining generated RPC message classes.
DependencyManager.prioritize_customer_dependencies() removes/re-adds the worker dependency path. _remove_module_cache() exempts proxy_worker.*, but evicts google.protobuf.* and google._upb._message resolved from that path.
Customer import of google.protobuf.timestamp_pb2 (or the native module itself) can reload the same worker _message.pyd if no separate customer Protobuf wins resolution.
The worker still holds its original RPC types. Dispatcher.on_logging() reads protos.RpcLog.Error and the process crashes inside _message.pyd.
Host reports the child process failure. Its subsequent Value cannot be null. (Parameter 'provider') is secondary, not evidence of a model-provider configuration error.
The original application also encountered ImportError: cannot import name 'df_dumps' from 'azure.functions._durable_functions': new Durable dependencies were resolved against an older worker SDK. Logging that ordinary Python exception exposed the secondary native crash. SDK selection and native-module lifetime are separate problems.
Reproduction A: actual worker cache transition, without host
Run each case in a disposable subprocess: the failing case intentionally terminates Python. Do not run this in a live worker or shared interpreter. No installed package modifications are required.
On both inspected worker releases, the failing case reports native module eviction and the same native file before/after, then faults when reading the enum.
Reproduction B: reduce further to Protobuf only
In the same isolated Python process setup, prepend a directory containing one tested Protobuf distribution to sys.path, then execute:
Omitting the delete/reimport yields 1. The failing variant also reproduces with python -I and while keeping an extra strong reference to the original native module.
Python
Protobuf
Control
Delete/reimport
3.13.15
5.29.6
Exit 0
Native access violation
3.13.15
6.33.6
Exit 0
Native access violation
3.14.0
6.33.5
Exit 0
Native access violation
The Python 3.14 row is a standalone native reproduction, not a claim that every 3.14 Functions app crashes. It also does not imply arbitrary native-module unloading must be supported by Protobuf; the worker must avoid invalidating its own live objects regardless.
Actual host observations and controls
A minimal HTTP application imports google.protobuf.timestamp_pb2 at module scope and calls logging.error(...) before defining its route. No A2A, Durable, model connection, or customer Protobuf installation is needed in the empty-venv case.
Scenario
Result
4.10.0, ordinary global interpreter, no PYTHONPATH override
Native crash; Protobuf resolves to worker bundle
4.14.0, same app/interpreter environment
HTTP 200; Protobuf resolves to global customer site-packages
4.14.0, empty venv, no customer Protobuf or PYTHONPATH override
Native crash; Protobuf resolves to worker bundle
Earlier baseline app: logging without native-loading import
Succeeds (two runs)
Earlier timestamp import + logging
Crashes (two runs)
Earlier plain import google.protobuf + logging
Succeeds
Earlier PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python control
No native crash
For the empty-venv case, create a venv with python -m venv --without-pip, activate/select its interpreter, and point Core Tools at a minimal HTTP app. Keep PYTHONPATH and PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION unset. Confirm the selected interpreter and module paths in diagnostics; merely having a venv directory is insufficient.
A native debugger identified a null-pointer read at address 0x18 inside _message.pyd for the 5.29.6 reproduction. No private symbols were available, so no exact internal C function/source line is asserted.
Upgrade / workaround status
Core Tools 4.14.0 contains fix: fix default cx deps path for 3.13 #1833, which prioritizes local interpreter site-packages when the customer path was not otherwise found. This avoids the original symptom when a compatible customer dependency closure exists. It does not fix the empty-venv native fallback case.
With 4.14.0, the A2A application factory returned Agent Card HTTP 200 both in the existing global environment and in a separate external venv exposing existing physical non-editable dependencies, without PYTHONPATH/source injection. The latter used a directory junction to an existing package target, not a fresh pip-install run. No model call or Durable workflow execution was performed in this comparison.
Selecting pure-Python Protobuf avoided the native crash in a diagnostic control, but is process-wide, has unmeasured performance/compatibility impact, and does not independently resolve the SDK mismatch. Treat as a temporary diagnostic option, not a qualified application fix.
Do not patch shared Core Tools files or ship arbitrary dependency pins as the solution.
Candidate permanent fix (proposal, not validated implementation)
Maintain one coherent worker-owned Protobuf family for the entire lifetime of worker RPC objects while allowing customer packages to resolve independently.
A candidate to prototype is a private, worker-owned pure-Python Protobuf runtime plus generated RPC/well-known types under the proxy worker namespace. Rewrite static/dynamic imports consistently, choose the implementation only inside that private family, and keep it out of customer cache eviction. Preserve the same family across the proxy-to-library protos interface, RPC serialization, descriptors, and callbacks. Do not alias it into public google.protobuf, shadow the google namespace, or force the customer's implementation via a process-wide environment variable.
Measure RPC serialization throughput, large-payload latency, CPU, and memory before approving pure Python. Performance budgets require maintainer agreement. If unsuitable, consider genuinely independent native-module state/build isolation or a larger process boundary. Renaming/copying a .pyd alone does not prove isolation.
Prior art #1873/#1876 applies to Python <=3.12, not this 3.13 proxy path. In particular, public aliases/process-wide settings in that fallback should not be copied blindly into a customer-independent design.
Experiments in an isolated worker copy explain why smaller patches are insufficient: preserving only the native module produced Python Message identity errors; preserving the entire public Protobuf family avoided the crash but broke customer Protobuf 6 generated code against worker runtime 5.29.6. Conditional preservation based on file existence was diagnostic only, not a portable fix.
Related #1906 concerns a different asymmetric namespace eviction/AttributeError in the classic worker. Regression coverage should include that namespace integrity constraint; purging an entire family is not safe if live worker native types remain.
Acceptance Criteria
A released-worker regression demonstrates the native fault in a bounded subprocess/actual host, without A2A, Durable, cloud credentials, or editable imports.
On the corrected worker, dependency switching never invalidates the Protobuf family backing retained worker RPC objects. Indexing, logging, enum/descriptor access, and RPC serialization succeed in the formerly failing host scenario. Tests should assert the lifetime invariant, not require a particular vendoring mechanism.
Cover no customer Protobuf, same-version customer Protobuf, newer customer runtime/gencode, and explicitly selected customer pure-Python implementation. A base HTTP app must not need to install Protobuf just to prevent a worker crash.
Customer public package resolution and native implementation remain independent; no Message identity/descriptor-pool/version errors, and no google.cloud/google.api_core namespace regression.
App-local packages, external venvs, explicit customer paths, startup, specialization, and reload are covered across supported Python versions/platforms. Windows 3.13 is mandatory for this regression; do not claim Linux/macOS reproduction until tested.
Ordinary application import/configuration errors are reported with useful diagnostics instead of native exit or silent empty indexing. Track incompatible Functions SDK selection separately.
Proxy/library integration, base HTTP, physical-wheel A2A startup/request execution, and Durable workflow behavior are exercised; preserve the host wire contract.
Benchmark the chosen implementation and meet maintainer-agreed resource/latency budgets before release.
Validate packaged worker artifacts and the consuming Host/Core Tools release, not just an editable checkout.
The standalone Protobuf-only delete/reimport reproducer may remain an upstream Protobuf concern even if the worker stops taking that unsafe path. Fixing the worker does not require promising arbitrary customer sys.modules manipulation is safe.
Suggested handoff sequence
Reproduce against the exact 4.45.1 bundle and read the tagged dependency-manager/proxy-library interfaces.
Add focused subprocess regressions; retain the original reproducer as the failing baseline.
Review/prototype coherent private isolation in a dedicated worker worktree, not by modifying the shared CLI installation.
Resolve SDK selection as a separate track, then expand lifecycle/platform/performance coverage.
Summary
On Windows, the Python 3.13 proxy worker can exit with
0xC0000005during indexing/logging after dependency isolation evicts Protobuf modules while retaining worker-generated RPC message classes. Reimporting the samegoogle._upb._messagebinary and then accessing a retained generated type is sufficient to reproduce a native access violation. Different Protobuf versions, A2A, Durable, gRPC, and the Functions host are not required for the smallest reproduction.Originally investigated through Azure/azure-functions-agents-runtime#211. The application's earlier physical-versus-editable packaging explanation was superseded by controlled reproductions. This issue tracks the worker/native-module lifetime defect, not an A2A implementation bug.
Still reproducible in the actual host bundled with Core Tools 4.14.0, using an empty Python 3.13 venv without customer Protobuf. Upgrading does improve a different dependency-resolution path; see below.
Environment and release chain
The host versions'
eng/build/Workers.Python.propsspecify the worker releases. Because that package reference excludes Windows, the actual downloaded Windows Core Tools distribution and startup logs were also inspected. Worker 4.46.0 is a separate release, not the worker bundled in Core Tools 4.14.0; a 4.46.0 host comparison has not been performed.Observed failure chain
proxy_worker.protos, retaining generated RPC message classes.DependencyManager.prioritize_customer_dependencies()removes/re-adds the worker dependency path._remove_module_cache()exemptsproxy_worker.*, but evictsgoogle.protobuf.*andgoogle._upb._messageresolved from that path.google.protobuf.timestamp_pb2(or the native module itself) can reload the same worker_message.pydif no separate customer Protobuf wins resolution.Dispatcher.on_logging()readsprotos.RpcLog.Errorand the process crashes inside_message.pyd.Value cannot be null. (Parameter 'provider')is secondary, not evidence of a model-provider configuration error.Relevant tagged sources: dependency.py, dispatcher.py.
The original application also encountered
ImportError: cannot import name 'df_dumps' from 'azure.functions._durable_functions': new Durable dependencies were resolved against an older worker SDK. Logging that ordinary Python exception exposed the secondary native crash. SDK selection and native-module lifetime are separate problems.Reproduction A: actual worker cache transition, without host
Run each case in a disposable subprocess: the failing case intentionally terminates Python. Do not run this in a live worker or shared interpreter. No installed package modifications are required.
Save as
worker_cache_repro.py:PowerShell, using the Python 3.13 bundle from an extracted Core Tools ZIP:
On both inspected worker releases, the failing case reports native module eviction and the same native file before/after, then faults when reading the enum.
Reproduction B: reduce further to Protobuf only
In the same isolated Python process setup, prepend a directory containing one tested Protobuf distribution to
sys.path, then execute:Omitting the delete/reimport yields
1. The failing variant also reproduces withpython -Iand while keeping an extra strong reference to the original native module.The Python 3.14 row is a standalone native reproduction, not a claim that every 3.14 Functions app crashes. It also does not imply arbitrary native-module unloading must be supported by Protobuf; the worker must avoid invalidating its own live objects regardless.
Actual host observations and controls
A minimal HTTP application imports
google.protobuf.timestamp_pb2at module scope and callslogging.error(...)before defining its route. No A2A, Durable, model connection, or customer Protobuf installation is needed in the empty-venv case.import google.protobuf+ loggingPROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=pythoncontrolFor the empty-venv case, create a venv with
python -m venv --without-pip, activate/select its interpreter, and point Core Tools at a minimal HTTP app. KeepPYTHONPATHandPROTOCOL_BUFFERS_PYTHON_IMPLEMENTATIONunset. Confirm the selected interpreter and module paths in diagnostics; merely having a venv directory is insufficient.A native debugger identified a null-pointer read at address
0x18inside_message.pydfor the 5.29.6 reproduction. No private symbols were available, so no exact internal C function/source line is asserted.Upgrade / workaround status
Candidate permanent fix (proposal, not validated implementation)
Maintain one coherent worker-owned Protobuf family for the entire lifetime of worker RPC objects while allowing customer packages to resolve independently.
A candidate to prototype is a private, worker-owned pure-Python Protobuf runtime plus generated RPC/well-known types under the proxy worker namespace. Rewrite static/dynamic imports consistently, choose the implementation only inside that private family, and keep it out of customer cache eviction. Preserve the same family across the proxy-to-library
protosinterface, RPC serialization, descriptors, and callbacks. Do not alias it into publicgoogle.protobuf, shadow thegooglenamespace, or force the customer's implementation via a process-wide environment variable.Measure RPC serialization throughput, large-payload latency, CPU, and memory before approving pure Python. Performance budgets require maintainer agreement. If unsuitable, consider genuinely independent native-module state/build isolation or a larger process boundary. Renaming/copying a
.pydalone does not prove isolation.Prior art #1873/#1876 applies to Python <=3.12, not this 3.13 proxy path. In particular, public aliases/process-wide settings in that fallback should not be copied blindly into a customer-independent design.
Experiments in an isolated worker copy explain why smaller patches are insufficient: preserving only the native module produced Python Message identity errors; preserving the entire public Protobuf family avoided the crash but broke customer Protobuf 6 generated code against worker runtime 5.29.6. Conditional preservation based on file existence was diagnostic only, not a portable fix.
Related #1906 concerns a different asymmetric namespace eviction/AttributeError in the classic worker. Regression coverage should include that namespace integrity constraint; purging an entire family is not safe if live worker native types remain.
Acceptance Criteria
google.cloud/google.api_corenamespace regression.The standalone Protobuf-only delete/reimport reproducer may remain an upstream Protobuf concern even if the worker stops taking that unsafe path. Fixing the worker does not require promising arbitrary customer
sys.modulesmanipulation is safe.Suggested handoff sequence
No permanent worker fix has been implemented or benchmarked yet.