4848from grapharc .cli .output import EXIT_FAILED , EXIT_OK , emit , fail
4949from grapharc .observe .metrics import summarize , to_mermaid
5050from grapharc .observe .replay import ReplayError
51- from grapharc .observe .trace import TraceRecorder
51+ from grapharc .observe .trace import TraceReadError , TraceRecorder
5252
5353EXAMPLES = (
5454 "stage0" ,
@@ -491,7 +491,13 @@ def _cmd_trace(args: argparse.Namespace) -> int:
491491 recorder = _existing_trace (args .path , command = "trace" , as_json = args .json )
492492 if isinstance (recorder , int ):
493493 return recorder
494- events = recorder .read_events (args .run_id )
494+ try :
495+ events = recorder .read_events (args .run_id )
496+ except TraceReadError as exc :
497+ # A bad line — a truncated write, a hand edit — is the "unreadable
498+ # trace" the exit-code contract names, not a traceback. Same for
499+ # `metrics` and `viz` below: all three read this file.
500+ return fail (str (exc ), as_json = args .json , command = "trace" )
495501 payload : dict [str , Any ] = {
496502 "ok" : True ,
497503 "command" : "trace" ,
@@ -521,7 +527,10 @@ def _cmd_metrics(args: argparse.Namespace) -> int:
521527 recorder = _existing_trace (args .path , command = "metrics" , as_json = args .json )
522528 if isinstance (recorder , int ):
523529 return recorder
524- metrics = summarize (recorder , args .run_id )
530+ try :
531+ metrics = summarize (recorder , args .run_id )
532+ except TraceReadError as exc :
533+ return fail (str (exc ), as_json = args .json , command = "metrics" )
525534 if metrics is None :
526535 return fail (
527536 f"no events for run { args .run_id !r} in { args .path } " ,
@@ -544,6 +553,8 @@ def _cmd_viz(args: argparse.Namespace) -> int:
544553 return recorder
545554 try :
546555 mermaid = to_mermaid (recorder , args .run_id )
556+ except TraceReadError as exc :
557+ return fail (str (exc ), as_json = args .json , command = "viz" )
547558 except ReplayError as exc :
548559 # Every other reading command answers this as a document; `viz` used to
549560 # let it out as a traceback with empty stdout, which breaks the CLI's own
0 commit comments