fix(dify-builder): keep Run.error in every verify handler

run_draft populates Run.error, and all three consumers threw it away:
Build and Edit assigned run_error = "" and Fix's Run(...) literal had no
error= at all. A launch failure therefore persisted with an empty error
(the long-open "TRUNCATED_STREAM_ERROR not persisted, err_len=0" item),
diagnose saw nothing, and the repair breaker -- which keys a launch
failure on run.error -- could never fire on one.

Fix's handle_verify also gains the try/except Build and Edit already
have, so a run_draft that raises degrades to a failed Run carrying the
launch error instead of killing the advance.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Charles YaoandClaude Opus 5 committed 2026-09-21 20:58:27 -07:00
1 parent f862fe327e
commit 87f00a8308
6 files changed
+122 -3

No files matched your search

+1 -1
View File
@@ -742,7 +742,7 @@ def handle_test_and_repair(env: Env, turn: Turn, s: Session, fc: DifyBuilderCont
try:
raw = env.dify.run_draft(s.app_id, turn.actor, inputs, emit, on_workflow_event=env.emit_workflow)
status, per_node, dify_run_id, run_error = raw.status, raw.per_node, raw.dify_run_id, ""
status, per_node, dify_run_id, run_error = raw.status, raw.per_node, raw.dify_run_id, raw.error
except Exception as exc:
# Never crash the advance; capture the launch error (log + store) instead
# of swallowing it, so diagnose/routing have something to act on.
+1 -1
View File
@@ -397,7 +397,7 @@ def handle_test_affected_paths(env: Env, turn: Turn, s: Session, fc: DifyBuilder
try:
raw = env.dify.run_draft(s.app_id, turn.actor, inputs, emit, on_workflow_event=env.emit_workflow)
status, per_node, dify_run_id, run_error = raw.status, raw.per_node, raw.dify_run_id, ""
status, per_node, dify_run_id, run_error = raw.status, raw.per_node, raw.dify_run_id, raw.error
except Exception as exc:
# Never crash the advance; capture the launch error (log + store) instead
# of swallowing it, so diagnose/routing have something to act on.
+8 -1
View File
@@ -701,7 +701,13 @@ def handle_verify(env: Env, turn: Turn, s: Session, fc: DifyBuilderContext) -> S
def emit(event: NodeEvent) -> None:
progress.observe_node("fix-run-validation", event)
result = env.dify.run_draft(s.app_id, turn.actor, inputs, emit, on_workflow_event=env.emit_workflow)
try:
result = env.dify.run_draft(s.app_id, turn.actor, inputs, emit, on_workflow_event=env.emit_workflow)
except Exception as exc:
# Same degrade as Build/Edit: never crash the advance; the launch error
# is captured on the Run (log + store) so the decision gate can show it.
logger.exception("dify_builder verify run failed to launch (session=%s, app=%s)", s.id, s.app_id)
result = Run(kind="verify", status="failed", per_node=[], error=launch_error_text(exc))
if result.status == "succeeded":
progress.complete("fix-run-validation")
else:
@@ -720,6 +726,7 @@ def handle_verify(env: Env, turn: Turn, s: Session, fc: DifyBuilderContext) -> S
dify_run_id=result.dify_run_id,
status=result.status,
per_node=result.per_node,
error=result.error,
inputs_ref=fc.test_input_ref,
immutable=True,
)