Skip to content

fix[parser]: wrap unhandled parser exceptions in CompilerPanic - #5191

Open
Sporarum wants to merge 16 commits into
vyperlang:masterfrom
Sporarum:fix-recursion
Open

Sporarum wants to merge 16 commits into
vyperlang:masterfrom
Sporarum:fix-recursion

Conversation

@Sporarum

Copy link
Copy Markdown
Collaborator

What I did

Catch unexpected exceptions raised during parsing (e.g. RecursionError from
deeply nested types) and surface them as a CompilerPanic with a helpful
message, instead of letting them bubble up as raw Python tracebacks.

Fixes: #5157

How I did it

Any non-Vyper exception caught during parsing is
re-raised as CompilerPanic("unhandled exception during parsing: <Type>: <msg>")
with the original exception chained via raise ... from e.

How to verify it

  • uv run pytest tests/unit/ast/test_parser.py::test_deeply_nested_type_raises_compiler_panic
  • Try compiling a contract with a deeply nested type such as
    x: uint256[1][1][1]... (500 levels) — you should now get a CompilerPanic
    instead of a raw RecursionError traceback.

Commit message

fix[parser]: wrap unhandled parser exceptions as CompilerPanic

this commit wraps any non-Vyper exception raised out of `_parse_to_ast`
in a `CompilerPanic` so users get a useful compiler error instead.

Description for the changelog

Fix unexpected exceptions not being wrapped during parsing

Cute Animal Picture

Put a link to a cute animal picture inside the parenthesis-->

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2a3675bcdd

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread vyper/ast/parse.py
@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown

Gas Changes

No changes detected.

Summary

  • Total tests measured: 560
  • Changed: 0
  • Regressions (gas up): 0
  • Improvements (gas down): 0
  • New tests: 0
  • Deleted tests: 0
  • Newly failing: 0
  • Newly passing: 0

@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown

📊 Bytecode Size Changes (venom)

No changes detected.

Full bytecode sizes

Contract legacy-O2 legacy-Os -O2 -O3 -Os
curvefi/legacy/CurveStableSwapMetaNG.vy 24952 23578 19769 19059 18523
curvefi/amm/stableswap/meta_implementation/meta_implementation_v_700.vy 23610 22805 19565 18627 18314
curvefi/amm/stableswap/implementation/implementation_v_700.vy 24962 23769 19188 18363 18019
curvefi/legacy/CurveStableSwapNG.vy 24473 23298 18749 17981 17636
curvefi/amm/tricryptoswap/implementation/implementation_v_200.vy 20724 19959 17250 16689 16325
curvefi/amm/twocryptoswap/implementation/implementation_v_210.vy 17634 16894 14958 14376 14027
yearnfi/VaultV3.vy 19972 19063 14739 13818 13269
curvefi/legacy/CurveCryptoSwap2.vy 18947 18382 14619 14129 13954
yearnfi/VaultV2.vy 16676 15763 13258 12466 12049
curvefi/amm/stableswap/factory/factory_v_100.vy 14558 13978 11852 10780 10880
curvefi/gauge/child_gauge/implementation/implementation_v_110.vy 12338 11561 9781 9184 8795
curvefi/amm/stableswap/views/views_v_120.vy 12784 12368 9705 9059 9294
curvefi/gauge/child_gauge/implementation/implementation_v_100.vy 12017 11249 9514 8924 8538
curvefi/amm/tricryptoswap/math/math_v_200.vy 11189 11126 9029 8144 8170
curvefi/legacy/CurveCryptoMathOptimized3.vy 11188 11125 9028 8144 8170
curvefi/gauge/child_gauge/implementation/implementation_v_020.vy 10665 9947 8626 8100 7714
curvefi/registries/metaregistry/metaregistry_v_110.vy 7590 6732 6491 5710 5603
curvefi/helpers/router/router_v_110.vy 6717 6717 6251 5733 6035
curvefi/amm/tricryptoswap/views/views_v_200.vy 7821 7776 6111 5896 6045
curvefi/helpers/stable_swap_meta_zap/stable_swap_meta_zap_v_100.vy 7302 7067 5877 5350 5610
curvefi/amm/twocryptoswap/views/views_v_200.vy 6991 6946 5680 5479 5614
curvefi/registries/metaregistry/registry_handlers/stableswap/handler_v_110.vy 6633 6259 5533 4695 5238
curvefi/amm/twocryptoswap/math/math_v_210.vy 6800 6800 5506 5012 5039
curvefi/amm/twocryptoswap/factory/factory_v_200.vy 5540 5252 4617 3917 4047
curvefi/amm/tricryptoswap/factory/factory_v_200.vy 5246 5021 4483 3890 4020
curvefi/gauge/child_gauge/factory/factory_v_201.vy 4844 4547 3901 3675 3511
curvefi/registries/metaregistry/registry_handlers/tricryptoswap/handler_v_110.vy 4241 3939 3718 3334 3429
curvefi/registries/metaregistry/registry_handlers/twocryptoswap/handler_v_110.vy 4186 3884 3671 3251 3329
curvefi/gauge/child_gauge/factory/factory_v_100.vy 4183 3914 3408 3144 2971
yearnfi/VaultFactory.vy 3765 3617 2936 2158 2461
curvefi/registries/address_provider/address_provider_v_201.vy 2973 2782 2613 2440 2353
curvefi/helpers/rate_provider/rate_provider_v_101.vy 3260 3260 2535 2263 2296
curvefi/amm/stableswap/math/math_v_100.vy 3067 3046 2458 2253 2310
curvefi/helpers/rate_provider/rate_provider_v_100.vy 2847 2841 2273 1954 1974
curvefi/helpers/deposit_and_stake_zap/deposit_and_stake_zap_v_100.vy 2322 2316 1782 1611 1670
curvefi/governance/relayer/taiko/relayer_v_001.vy 2068 2064 1731 1510 1558
curvefi/governance/relayer/polygon_cdk/relayer_v_101.vy 1556 1523 1530 1324 1347
curvefi/governance/relayer/arb_orbit/relayer_v_101.vy 1266 1262 1242 1066 1115
curvefi/governance/relayer/op_stack/relayer_v_101.vy 1186 1182 1183 1014 1056
curvefi/governance/relayer/not_rollup/relayer_v_100.vy 1168 1153 1174 1011 1037
curvefi/governance/vault/vault_v_100.vy 964 941 862 823 839
curvefi/governance/relayer/relayer_v_100.vy 496 496 593 490 503
curvefi/governance/agent/agent_v_100.vy 541 541 430 402 406
curvefi/governance/agent/agent_v_101.vy 541 541 430 402 406

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c4b66767bf

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread vyper/ast/parse.py
Comment thread vyper/ast/parse.py

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1b07791338

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread vyper/ast/pre_parser.py Outdated
# https://docs.python.org/3/library/exceptions.html#SyntaxError.offset)
offset = e.offset
if offset is not None:
offset -= 1

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Point indentation errors at the offending indent

For IndentationError/TabError raised by tokenize, e.offset is the 1-based position after the offending logical line, not the indentation column; on the Python 3.12 CI workflow, the added return case reports offset 10, so this stores col 9 instead of the expected col 2. This makes the new indentation tests fail and points users at the end of the line rather than the bad indent; derive the indentation width from the error text/args for tokenizer indentation errors instead of only subtracting one.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Python 3.12 when adding support for PEP 701, tokenize was re-implemented in C (before, after).
One regression of this process was that now IndentationErrors have their e.offset set to end of line + 1
This remains the case all the way to the previews for 3.15
See python/cpython#153837

As a consequence, we cannot give accurate positions for these kinds of errors (unless we manually re-compute the offset)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed: 568464c (by manually re-computing the offset)

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 37e5ff8da0

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread vyper/exceptions.py Outdated
@charles-cooper charles-cooper changed the title fix[parser]: wrap unhandled parser exceptions as CompilerPanic fix[parser]: wrap unhandled parser exceptions in CompilerPanic Jul 20, 2026
Comment thread vyper/ast/pre_parser.py Outdated
offset -= 1
raise SyntaxException(e.msg, code, e.lineno, offset) from e
except UnicodeEncodeError as e:
prefix = code[: e.start]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

explanation in this branch please

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See test_unpaired_surrogate_raises_syntax_exception

This seems like a super edge-case, but Codex suggested it, and it was fairly simple to implement.

Oh and every exception type we do not catch here is reported to the user as-is

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i meant an explanation in the code as a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't sure what kind of explanation you wanted, let me know what you think

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't think it's worth special handling tbh? or like the issue is not wrapping exceptions properly right? if we really care about that why don't we have a fallback?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this PR we do this:

    except _BaseVyperException:
        raise
    except Exception as e:
        raise CompilerPanic(f"unhandled exception during parsing: {type(e).__name__}: {e}") from e

And so a UnicodeEncodeError bubbles up to the user as a CompilerPanic, even though that is not an issue of the compiler, but of the input file.

We could do the opposite assumption, and do something like:

...
    except Exception as e:
        raise ParserException(f"{type(e).__name__}: {e}")

But this risks showing internal mistakes as ParserExceptions

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 54e5650e32

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread vyper/ast/parse.py
@charles-cooper

Copy link
Copy Markdown
Member

approved but i would recommend splitting out the change implied by the PR title from the other changes

Comment thread vyper/ast/pre_parser.py

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f198341816

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread vyper/ast/parse.py
Comment thread vyper/ast/parse.py
Comment thread vyper/ast/parse.py
Comment thread vyper/ast/utils.py Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9af7378ce6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread vyper/ast/parse.py

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e119edcc2c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread vyper/ast/pre_parser.py
Comment thread vyper/ast/parse.py
e.resolved_path = resolved_path
raise e
except Exception as e:
raise CompilerPanic(f"unhandled exception during parsing: {type(e).__name__}: {e}") from e

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think dumping e as a string and also its type is redundant given the exception chain (from e)

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.

Deeply nested array type crashes with raw RecursionError

2 participants