CircuitPython version and board name
Adafruit CircuitPython 10.2.1 on <date>; Adafruit Circuit Playground Bluefruit with nRF52840
Code/REPL
print("You Are Awesome!) # missing closing quote → SyntaxError
Behavior
After the code ends with an uncaught exception (SyntaxError or NameError — the traceback prints correctly to the serial console), the status NeoPixel blinks GREEN once every 5 seconds — the "code finished without error" pattern.
Expected, per the Learn guide troubleshooting page and docs (https://learn.adafruit.com/welcome-to-circuitpython/troubleshooting): "2 RED blinks: Code ended due to an exception."
The red exception blink never appears for any exception I can produce. Additionally, the serial status bar / terminal title shows "Done" after an exception rather than the line@file ExceptionName form.
Description
This looks like a return-code scheme mismatch introduced when the MicroPython v1.25-era shared/runtime/pyexec.c (new exit-code scheme) was merged, while main.c still tests the old flag value:
main.c line 588 (tag 10.2.1; line ~579 on main — still present):
if (_exec_result.return_code != PYEXEC_EXCEPTION) {
...
color = ALL_DONE; ...
} else {
color = EXCEPTION;
blink_count = EXCEPTION_BLINKS;
}
shared/runtime/pyexec.h (10.2.1): PYEXEC_EXCEPTION is the old bit flag (0x200), but the new scheme defines PYEXEC_UNHANDLED_EXCEPTION as (1) (with MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING) or (0) (without).
shared/runtime/pyexec.c (10.2.1), parse_compile_execute: on an uncaught exception it sets ret = PYEXEC_UNHANDLED_EXCEPTION; (line 233) and stores it via result->return_code = ret; (line 244). Nothing in pyexec.c ever returns 0x200 anymore, so return_code != PYEXEC_EXCEPTION is always true and the red EXCEPTION branch in main.c is unreachable — every exception shows the green ALL_DONE blink.
The same stale test appears at main.c line 272 (10.2.1) in supervisor_execution_status():
c
} else if ((_exec_result.return_code & PYEXEC_EXCEPTION) != 0 && ...
which is why the status bar reports "Done" after an exception.
For contrast, on the 9.2.x branch shared/runtime/pyexec.c line 204 still set ret = PYEXEC_EXCEPTION;, so the red blink worked there — this is a 10.x regression.
Additional information
Nearby code in main.c (e.g. the _exec_result.return_code == 0 success test around line 549) already uses the new scheme, so the fix is presumably to update the two remaining old-scheme tests to check PYEXEC_UNHANDLED_EXCEPTION / nonzero-and-not-special-flag as appropriate.
Thanks for your work!!!
CircuitPython version and board name
Code/REPL
Behavior
After the code ends with an uncaught exception (SyntaxError or NameError — the traceback prints correctly to the serial console), the status NeoPixel blinks GREEN once every 5 seconds — the "code finished without error" pattern.
Expected, per the Learn guide troubleshooting page and docs (https://learn.adafruit.com/welcome-to-circuitpython/troubleshooting): "2 RED blinks: Code ended due to an exception."
The red exception blink never appears for any exception I can produce. Additionally, the serial status bar / terminal title shows "Done" after an exception rather than the line@file ExceptionName form.
Description
This looks like a return-code scheme mismatch introduced when the MicroPython v1.25-era shared/runtime/pyexec.c (new exit-code scheme) was merged, while main.c still tests the old flag value:
main.c line 588 (tag 10.2.1; line ~579 on main — still present):
shared/runtime/pyexec.h (10.2.1): PYEXEC_EXCEPTION is the old bit flag (0x200), but the new scheme defines PYEXEC_UNHANDLED_EXCEPTION as (1) (with MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING) or (0) (without).
shared/runtime/pyexec.c (10.2.1), parse_compile_execute: on an uncaught exception it sets ret = PYEXEC_UNHANDLED_EXCEPTION; (line 233) and stores it via result->return_code = ret; (line 244). Nothing in pyexec.c ever returns 0x200 anymore, so return_code != PYEXEC_EXCEPTION is always true and the red EXCEPTION branch in main.c is unreachable — every exception shows the green ALL_DONE blink.
The same stale test appears at main.c line 272 (10.2.1) in supervisor_execution_status():
which is why the status bar reports "Done" after an exception.
For contrast, on the 9.2.x branch shared/runtime/pyexec.c line 204 still set ret = PYEXEC_EXCEPTION;, so the red blink worked there — this is a 10.x regression.
Additional information
Nearby code in main.c (e.g. the _exec_result.return_code == 0 success test around line 549) already uses the new scheme, so the fix is presumably to update the two remaining old-scheme tests to check PYEXEC_UNHANDLED_EXCEPTION / nonzero-and-not-special-flag as appropriate.
Thanks for your work!!!