Recording “time of first raise” timestamps as a “Deferred, but not rejected” idea sounds good to me. It might be possible, but it’s not obviously easy, and it’s far from clear that it’s necessary, so including it in the initial iteration carries a high risk of introducing significant complexity for negligible benefit.
We can do this with monitoring:
import sys
from datetime import datetime
# Define a tool ID
TOOL_ID = sys.monitoring.DEBUGGER_ID
sys.monitoring.use_tool_id(TOOL_ID, "ExceptionEnricher")
def on_exception(code, instruction_offset, exc):
timestamp = datetime.now().isoformat()
exc.add_note(f"Intercepted at: {timestamp}")
# Register the callback for raised exceptions
sys.monitoring.register_callback(TOOL_ID, sys.monitoring.events.RAISE, on_exception)
sys.monitoring.set_events(TOOL_ID, sys.monitoring.events.RAISE)
try:
1/0
except:
raise ValueError
Output:
Traceback (most recent call last):
File "/Users/iritkatriel/src/tt.py", line 19, in <module>
1**/**0
\~**^**\~
**ZeroDivisionError**: division by zero
Intercepted at: 2026-04-15T22:31:49.170785
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/iritkatriel/src/tt.py", line 21, in <module>
raise ValueError
ValueError
Intercepted at: 2026-04-15T22:31:49.170810
Would it be possible/make sense to format the timestamp like that instead of changing str(exc)? It may avoid the need for traceback.strip_exc_timestamps() in some cases.
I think it would be better to add the timestamp output to the traceback’s first line, rather than altering the exception’s string, which is often used and parsed by real life applications and logging tools in lots of ways which would break:
Traceback (most recent call last, raised at 2026-04-12T18:07:30.346914Z):
File "<stdin>", line 3, in california_raisin
raise RuntimeError("not enough sunshine")
RuntimeError: not enough sunshine
The output also looks more readable that way.
Yes sys.monitoring could be used to do this today. But that is a heavyweight call and very heavyweight note. It’d impact application performance (including the pathological StopIteration and StopAsyncIteration cases).
I’ll make sure to cover this in the next update.
I think the ‘heavyweight’ claim requires benchmarking.
Note that there is a C API for monitoring.
Round 2: I’ve posted PR peps#4928 with edits incorporating feedback so far. The implementation has also been updated. short summary:
I dropped the us format in favor of just ns (now using decimal seconds) and iso options. (trivial to add ms and us as well but I don’t see a point in the complexity)
no_timestamp= was renamed to timestamps= in the traceback module APIs and I did wind up going with the tri-state as I came up with a reason why someone might want it.
Various clarifications that came up here that needed recording as more detail or recording either as rejected ideas or open issues (and sometimes both… rejected, but open to exploring, deferring? etc)
sys.monitoring - I dug into that a bit more and describe how it could be used and what it would require… which led to me deciding that was a rejected ideas piece more so than open issue: The RAISE event fires too often, the call overhead on all of those events is high, and it’d involve additional memory allocations and potentially collectable objects created upon every raise.
Lets please keep non-docs editorial discussion here rather than as PR comments. Far more details in the PEP update itself. Please read it. I’ll reply here once it has merged and published. For now, see the PR.
PR merged. It looks published. The PR is the easiest way to see the diff.
The SC has discussed and while we are generally positive about PEP 830 - Add timestamps to exceptions and tracebacks, we have decided to defer making a decision on this PEP until Python 3.16. We have feedback on collection and on the opt-in/display story that we’d like to see worked through before we make a decision.
On the collection:
- The current performance numbers do not cover Windows or shared-library configurations (which may see significantly more overhead). We’d like to see numbers for those environments incorporated into the PEP so we can better evaluate the overhead claim across platforms.
- Pickle output depends on the timestamp collection state, which we find awkward. We’d prefer an opt-out, either by not collecting, or by not pickling the timestamp attribute even when collection is enabled.
On opt-in and display:
- The PEP appeals to CPython convention to justify silent-ignore on invalid env var values, but that convention is really for boolean toggles (e.g.
PYTHONFAULTHANDLER,PYTHONDEVMODE) and not for enum-shaped flags (e.g.PYTHON_GIL,PYTHON_FROZEN_MODULES,PYTHONTRACEMALLOC,PYTHON_CPU_COUNT,PYTHONHASHSEED). Enum-shaped flags by and large fail-fatal on invalid values, andPYTHON_TRACEBACK_TIMESTAMPSshould follow the convention of that peer group. This behavior should also be aligned across the env var and-Xpaths to avoid a confusing user experience and bifurcation of documentation. PYTHON_TRACEBACK_TIMESTAMPSand-X traceback_timestamps=should accept one value per meaning. Each precision option should have a single canonical string (e.g.ns,us,ms,iso), with an explicitofffor disabled. Equivalents likeempty,0, and1should be rejected as invalid rather than silently aliased to one of the canonical values.- The current proposed timestamp suffix appears on the message line in formatted traceback output and is per-occurrence, which means tooling that captures stderr or formatted tracebacks and matches on the message line sees a different string for every exception instance. The discussion thread raised header-line placement as an alternative that avoids this. We don’t think message-line placement is necessarily wrong, but the PEP should further justify the choice with a clear rationale and close out the open issue regarding display location. Further, placing the timestamp at the end of the line obscures it in ways that can be difficult to see.
- Opt-out for doctest printing will likely break code and is backward incompatible. This is because doctests can be very sensitive to display output. We’d prefer an opt-in flag, e.g.
doctest.INCLUDE_EXCEPTION_TIMESTAMPSwhich are not enabled by default. - Similarly
test.support.force_no_traceback_timestampsshould probably be enabled by default, possibly with a differently named flag to enable traceback timestamps in the stdlib test suite.
Thanks again for your work on this PEP, we look forward to discussing again with revisions.