Skip to content

docs(genlayer-py-std): clarify unpack_result vs run_nondet return values - #11

Open
ygd58 wants to merge 1 commit into
genlayerlabs:v0.3.xfrom
ygd58:docs/clarify-nondet-unpack-result
Open

docs(genlayer-py-std): clarify unpack_result vs run_nondet return values#11
ygd58 wants to merge 1 commit into
genlayerlabs:v0.3.xfrom
ygd58:docs/clarify-nondet-unpack-result

Conversation

@ygd58

@ygd58 ygd58 commented Jul 30, 2026

Copy link
Copy Markdown

Summary

Fixes the confusion reported in genlayerlabs/genvm#322 — that repo is archived and moved here, so filing the fix against the current source location.

gl.vm.unpack_result(gl.vm.run_nondet_unsafe(leader_fn, validator_fn)) (or the current run_nondet/run_nondet_default) crashes with:

AttributeError: 'dict' object has no attribute 'calldata'

Root cause

run_nondet and run_nondet_default both go through _decode_sub_vm_result, which already calls unpack_result() internally before returning — so their return value is the plain decoded leader value, not a Result/Return wrapper. Calling unpack_result() on it again crashes, since a plain dict/int/etc. has no .calldata attribute.

This is easy to get wrong because the validator_fn callback does receive a proper Result (with .calldata, isinstance(x, Return) works as expected) for both functions — only the final return value is already unwrapped. The asymmetry isn't obvious from the API surface.

This is not a behavior bugrun_nondet/run_nondet_default are working as designed, and changing their return type would break every existing caller that (correctly) uses the value directly, as already shown in run_nondet_default's own docstring example. The actionable fix is documentation clarity, per the issue's own "Ask".

Change

Docstring-only, no behavior change:

  • run_nondet: explicitly states the return value is already unwrapped and must not be passed to unpack_result() again; notes the validator_fn/return-value asymmetry.
  • run_nondet_default: same clarification, cross-referencing run_nondet.
  • unpack_result: added a note on which vm functions' outputs need it (spawn_sandbox, validator_fn results) versus which don't (run_nondet, run_nondet_default return values).

Note: genvm#322 lives in the now-archived genlayerlabs/genvm repo, which is read-only, so I couldn't comment there directly — linking it here instead.

Summary by CodeRabbit

  • Documentation
    • Clarified VM result-handling behavior for nondeterministic execution.
    • Documented that nondeterministic calls return already-unwrapped values and should not be passed to unpack_result.
    • Expanded return-value guidance and examples, including validator behavior.

run_nondet() and run_nondet_default() already return the plain decoded
leader value (they internally call unpack_result() on the RunNondet
sub-vm result before returning), unlike spawn_sandbox() which returns a
raw Result that still needs unpack_result().

Calling unpack_result() a second time on a run_nondet(_default) return
value crashes with:

    AttributeError: 'dict' object has no attribute 'calldata'

because the value has already been unwrapped and is a plain object,
not a Return/Result wrapper.

This is easy to get wrong because validator_fn *does* receive a proper
Result (with .calldata, isinstance(x, Return) works) for both
functions - only the final return value differs. Clarified the
docstrings of run_nondet, run_nondet_default, and unpack_result to
make the asymmetry explicit and cross-reference each other.

No behavior change - docstrings only.

Addresses the confusion reported in genlayerlabs/genvm#322 (that repo
is archived/moved here, so filed against the current source location).
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

VM documentation now clarifies that run_nondet and run_nondet_default return already-unwrapped values, while unpack_result applies to Result values such as validator inputs.

Changes

VM result-unwrapping documentation

Layer / File(s) Summary
Result-unwrapping API documentation
runners/genlayer-py-std/src/genlayer/vm/__init__.py
Docstrings distinguish Result inputs from already-unwrapped nondeterministic outputs, warn against re-unpacking, and update the run_nondet example.

Estimated code review effort: 1 (Trivial) | ~3 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the doc-only change and the main clarification about unpack_result versus run_nondet return values.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant