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
{{ message }}
Repository navigation
direct_deploy fails with calldata decoding error on 0.30.0rc2 (regression from 0.29.2) #113
Versions:genlayer-test 0.30.0rc2, genlayer-py 0.19.0rc2 (current release candidates as of testing)
Setup: GenVM bundle download confirmed working correctly — 325,563,524 bytes, completed in 1m21s (~3.9 MiB/s), not a network/timeout issue. Bundle caches correctly; direct_deploy no longer hangs on download after the first run.
Result: Deploying even a trivial contract via direct_deploy fails during SDK import, before the contract's constructor runs:
genlayer.py.calldata.DecodingError: unexpected end of memory
Confirmed NOT present on the prior stable release: reverting to genlayer-test 0.29.2 / genlayer-py 0.16.3 and running the identical direct-mode test (fixture-only, then trivial direct_deploy) passes cleanly: 2 passed in 0.24s. This isolates the decoding error specifically to the 0.30.0rc2/0.19.0rc2 pairing — looks like a regression introduced between stable and the current rc.
Related question, not a bug: on stable 0.29.2, direct_deploy supports deploying multiple Python contracts, but cross-contract calls (DeployContract, CallContract, PostMessage) only execute as real calls when a _gl_call_hook is installed, which the source comments describe as "for glsim mode." Without it, direct mode mocks web/LLM calls but has no default real execution path for @gl.evm.contract_interface reads against a separately deployed contract. Is this intended? If there’s a recommended way to exercise real cross-contract/EVM-interface calls in direct mode, a docs pointer would help — currently using Studio mode for that, which is blocked by the issue above.
Happy to share full logs or a minimal repro repo on request.
Tried to reproduce this with the exact reported version pairing and couldn't trigger the error — sharing what I tried in case it helps narrow down what's different in your environment.
Tried three variations, all against a trivial contract with "Depends": "py-genlayer:latest":
No-arg constructor, single direct_deploy("Trivial.py") call — passed.
Constructor with an actual arg, direct_deploy("TrivialArgs.py", 42) — passed (this seemed like the most likely trigger for a calldata-decoding error, since a no-arg constructor has essentially nothing to decode).
Your exact scenario shape — a fixture-only test followed by a trivial-deploy test in the same file/session — also passed, 2 passed in 0.12s, timing-wise similar to what you saw on stable.
None of these hit DecodingError: unexpected end of memory. I traced where message decoding happens in this path — load_contract_class injects the message via _inject_message_to_fd0 into fd 0 before genlayer is imported (comment in the source: "genlayer reads message from fd 0 at import time"), which is the "before the constructor runs" step you mentioned — but I couldn't get that path to fail with straightforward deploys.
A few things that might help narrow it down further, if you're up for sharing:
Full traceback (is the DecodingError raised from inside _inject_message_to_fd0/fd-0 read, or somewhere else during the SDK import — e.g. a schema/ABI generation step)?
Was this a genuinely fresh environment (no prior ~/.cache for genvm/genlayer bundles, no earlier pip installs of adjacent versions), or could an older cached GenVM bundle from a different version have been reused?
OS/Python version
The actual contract file, if it's not sensitive — mine were about as trivial as it gets, so if yours has something more specific (a particular arg type, dataclass, collection, etc.) that could be the actual trigger.
Follow-up with a narrowed minimal reproducer and full environment details.
Environment:
genlayer-test==0.30.0rc2
genlayer-py==0.19.0rc2
Python 3.12.3 on WSL/Linux
Fresh direct-mode GenVM bundle cache (the previous bundle cache was cleared and re-downloaded)
Failure occurs before the constructor executes, while importing the contract module
The real Governor contract reproduces the same failure, but the smallest probe that reproduced it was a contract with two Address-typed constructor arguments:
It was deployed with two address arguments through the direct-mode fixture. The temporary probe file was deleted after the test, so the snippet above records the minimal reproducer shape rather than claiming to be a byte-for-byte recovery of that deleted file.
The relevant traceback is:
spec.loader.exec_module(module)
... tests/_rc2_address_probe.py:6
class AddressProbe(gl.Contract):
... genlayer/gl/__init__.py
from genlayer._internal.msg import MessageRawType, message_raw as _message_raw_original
... genlayer/_internal/msg.py:69
message_raw = calldata.decode(io.FileIO(0, closefd=False).readall())
... genlayer/py/calldata.py:286
res = impl()
... genlayer/py/calldata.py:245
code = read_uleb128()
... genlayer/py/calldata.py:234
m = fetch_mem(1)[0]
... genlayer/py/calldata.py:224
raise DecodingError('unexpected end of memory')
genlayer.py.calldata.DecodingError: unexpected end of memory
ImportError: Failed to load contract: unexpected end of memory
This was reproduced with the minimal two-Address constructor and with contracts/governor.py. It was not isolated to DynArray, method count, or contract size. The stable 0.29.2/0.16.3 environment did not show this import-time failure in the earlier direct-mode run.
The earlier maintainer reproduction with no-arg, integer-arg, and fixture-plus-deploy probes passed, so the remaining distinction appears to be the Address-typed constructor argument path. Please let me know if you need the original temporary probe recreated or any additional environment output.
Reproduced on 0.30.0rc2 / 0.19.0rc2. Assigning to myself.
The trigger isn't Address constructor args. It fails for every shape I tried, including a no-arg contract:
ImportError: Failed to load contract: unexpected end of memory
Cause: the SDK moved its modules under genlayer.py, but gltest/direct/sdk_compat.py still imported genlayer.calldata / genlayer.types from the package root. That ImportError is swallowed by _inject_message_to_fd0, so the encoded message never reaches fd 0 and the SDK decodes real stdin instead.
Activity
ygd58 commentedon Sep 11, 2026
Tried to reproduce this with the exact reported version pairing and couldn't trigger the error — sharing what I tried in case it helps narrow down what's different in your environment.
Setup: fresh venv,
pip install genlayer-test==0.30.0rc2 genlayer-py==0.19.0rc2 --pre(confirmed exact versions viapip show).Tried three variations, all against a trivial contract with
"Depends": "py-genlayer:latest":direct_deploy("Trivial.py")call — passed.direct_deploy("TrivialArgs.py", 42)— passed (this seemed like the most likely trigger for a calldata-decoding error, since a no-arg constructor has essentially nothing to decode).2 passed in 0.12s, timing-wise similar to what you saw on stable.None of these hit
DecodingError: unexpected end of memory. I traced where message decoding happens in this path —load_contract_classinjects the message via_inject_message_to_fd0into fd 0 beforegenlayeris imported (comment in the source: "genlayer reads message from fd 0 at import time"), which is the "before the constructor runs" step you mentioned — but I couldn't get that path to fail with straightforward deploys.A few things that might help narrow it down further, if you're up for sharing:
DecodingErrorraised from inside_inject_message_to_fd0/fd-0 read, or somewhere else during the SDK import — e.g. a schema/ABI generation step)?~/.cacheforgenvm/genlayer bundles, no earlier pip installs of adjacent versions), or could an older cached GenVM bundle from a different version have been reused?Happy to try again with more specifics.
Snehal707 commentedon Sep 12, 2026
Follow-up with a narrowed minimal reproducer and full environment details.
Environment:
genlayer-test==0.30.0rc2genlayer-py==0.19.0rc2The real Governor contract reproduces the same failure, but the smallest probe that reproduced it was a contract with two
Address-typed constructor arguments:It was deployed with two address arguments through the direct-mode fixture. The temporary probe file was deleted after the test, so the snippet above records the minimal reproducer shape rather than claiming to be a byte-for-byte recovery of that deleted file.
The relevant traceback is:
This was reproduced with the minimal two-
Addressconstructor and withcontracts/governor.py. It was not isolated toDynArray, method count, or contract size. The stable0.29.2/0.16.3environment did not show this import-time failure in the earlier direct-mode run.The earlier maintainer reproduction with no-arg, integer-arg, and fixture-plus-deploy probes passed, so the remaining distinction appears to be the
Address-typed constructor argument path. Please let me know if you need the original temporary probe recreated or any additional environment output.HusseinAdeiza commentedon Sep 28, 2026
Reproduced on 0.30.0rc2 / 0.19.0rc2. Assigning to myself.
The trigger isn't
Addressconstructor args. It fails for every shape I tried, including a no-arg contract:Cause: the SDK moved its modules under
genlayer.py, butgltest/direct/sdk_compat.pystill importedgenlayer.calldata/genlayer.typesfrom the package root. That ImportError is swallowed by_inject_message_to_fd0, so the encoded message never reaches fd 0 and the SDK decodes real stdin instead.PR incoming.