The GitHub Actions job "Required Checks" on 
texera.git/gh-readonly-queue/main/pr-8768-5945cc81858e33db3d5280e9913e089f2035b3a6
 has failed.
Run started by GitHub user Xiao-zhen-Liu (triggered by Xiao-zhen-Liu).

Head commit for run:
57b7ae7b2c5c02a04e84a81645825422cd8780d4 / Suryaa Charan 
<[email protected]>
feat(pyamber): explain Python UDF load errors with cause and fix (#8768)

### What changes were proposed in this PR?

When a Python UDF fails to load, the error now says what to fix. The
existing "There should be one and only one Operator defined" sentence
stays first, so anything matching on it still works.

The line number and fix are attached as a note to the original
exception, so its type, message and attributes stay as raised. The RPC
server now includes exception notes in the `ControlError` message, which
is what the Static Error tab shows.

| Mistake | Message now adds |
|---|---|
| No class (e.g. the whole template left commented out) | `No Operator
class was found. Uncomment or write exactly one class...` |
| Method doesn't match the base class | `WrapperClass subclasses
UDFOperatorV2 but does not implement process_tuple. If you meant
process_table, subclass UDFTableOperator instead.` |
| Two classes | `Found 2: FirstOperator, SecondOperator. Keep one and
delete or comment out the others.` |
| Missing `from pytexera import *` | `name 'UDFOperatorV2' is not
defined (line 2 of the UDF code). Add from pytexera import * at the top
of the UDF.` |
| `@overrides` on the wrong method | the base class to method pairing |
| A class with two pytexera bases | `X uses more than one base class
(UDFOperatorV2, UDFTableOperator). Subclass exactly one.` |
| Any other load error | the line number in the user's code |

Before and after, in the Static Error tab. Before is the untouched
template; after is a class with the wrong method:

| Before | After |
|---|---|
| <img width="800" height="288" alt="load-before"
src="https://github.com/user-attachments/assets/bd2ac22c-1953-435c-b3d5-0cf2e6f0ddda";
/>| <img width="800" height="348" alt="load-after"
src="https://github.com/user-attachments/assets/53985c6f-9ad3-4d93-aed1-0974d14e85ad";
/> |

Missing import, after:

<img width="800" height="303" alt="load-after-import"
src="https://github.com/user-attachments/assets/c1ed1322-f7d0-4937-8aa2-848917a115ba";
/>


### Any related issues, documentation, discussions?

Part of #8736. Split out of #8737 as the reviewer asked.

### How was this PR tested?

New tests in `test_executor_manager.py` cover each case above, plus a
syntax error, a `KeyError` and a custom exception at load time (both
keep their own message and get the hint as a note), a class alias, and a
`LoopEndOperator` subclass. `test_async_rpc_server.py` covers notes in
`ControlError`, and loads a broken UDF inside a handler to check the
message that gets sent back.

```
cd amber
pytest -m "not integration" 
src/test/python/core/architecture/managers/test_executor_manager.py 
src/test/python/core/architecture/rpc/test_async_rpc_server.py
pytest -m "not integration"
ruff check src/main/python src/test/python && ruff format --check 
src/main/python src/test/python
```

The screenshots are from a local Texera built from this branch. The
displayed text for those cases is the same after the follow-up commit.

Known limitations: UI-parameter source-line mapping relies on the
generated hook's reserved name and structure. Runtime traceback
locations (e.g., errors inside process_tuple) are not remapped.

### Was this PR authored or co-authored using generative AI tooling?

Generated-by: Claude Code (Claude Opus 5.5)

---------

Co-authored-by: suryaacharan <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>

Report URL: https://github.com/apache/texera/actions/runs/38791367000

With regards,
GitHub Actions via GitBox

Reply via email to