Skip to content

fix: surface WorkflowAgent model stream error values without durable-step retries or duplicate callbacks - #18827

Merged
gr2m merged 7 commits into
mainfrom
bugfix-18824-20260813145943955344
Aug 18, 2026
Merged

fix: surface WorkflowAgent model stream error values without durable-step retries or duplicate callbacks#18827
gr2m merged 7 commits into
mainfrom
bugfix-18824-20260813145943955344

Conversation

@ai-sdk-factory

@ai-sdk-factory ai-sdk-factory Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Background

WorkflowAgent forwarded standard model stream error parts but discarded their original values from the server-side result.

Summary

  • Preserve the existing resolved-result behavior for model error finishes.
  • Expose the original error-part value as result.error, including falsy and undefined values (use 'error' in result to test presence).
  • Carry the value across the durable step boundary as data, avoiding automatic workflow-step retries and error normalization.
  • Invoke onError exactly once and document the new result field.
  • Add a patch changeset.

Testing

  • Workflow Node suite: 178 tests passed.
  • Workflow Edge suite: 178 tests passed.
  • Durable workflow integration suite: 20 tests passed.
  • pnpm type-check:full passed.
  • pnpm check passed.

Fixes #18824

ai-sdk-factory and others added 3 commits August 13, 2026 15:10
Co-authored-by: MintedKenny <104696466+MintedKenny@users.noreply.github.com>
Co-authored-by: MintedKenny <104696466+MintedKenny@users.noreply.github.com>
…145943955344

# Conflicts:
#	packages/harness-pi/src/pi-auth.test.ts
@ai-sdk-factory

Copy link
Copy Markdown
Contributor Author

Bugfix review

Outcome: changes-required

Reproduction replay

Status: no-longer-reproduces

The exact original reproduction completed successfully and the original bug signal did not appear.

Fixes issue

Status: partially-addresses

The fix works when doStreamStep executes as an ordinary function, but not reliably across its intended durable workflow step boundary.

Concerns:

  • doStreamStep is a "use step" function. Throwing part.error invokes automatic step retries rather than immediately delivering the terminal value to WorkflowAgent.
  • Workflow step failures are normalized into a new workflow error, so Error identity, structured classification, and falsy values are not preserved across the actual step boundary.

Side effects

Risk: high

A terminal model error can now retry the entire model step and can invoke the public onError callback twice.

Concerns:

  • The workflow runtime defaults failed steps to three retries, potentially repeating model requests and streamed error parts before failure.
  • streamTextIterator calls onError before rethrowing, and WorkflowAgent calls it again; a focused probe observed two callback invocations for one error part.

Performance

Risk: high

Automatic step retries can multiply model-call latency, provider usage, streaming work, and cost on every terminal error part.

Concerns:

  • doStreamStep has no step-level maxRetries override, so an ordinary thrown stream error follows the workflow runtime's default retry policy.

Backwards compatibility

Risk: none

No persisted-data schema or migration changes are introduced, and previously stored workflow data is unaffected.

Breaking changes

Risk: medium

WorkflowAgent.stream now rejects on an error part where it previously resolved with an error finish reason, which is an externally observable error-behavior change.

Concerns:

  • Existing consumers that handle finishReason="error" on a resolved result will instead receive a rejection.

Architecture

Risk: high

Package boundaries remain intact, but using a thrown arbitrary value to cross a durable step boundary conflicts with the workflow runtime's retry and error-normalization architecture.

Concerns:

  • The terminal value should be returned through a serializable typed step result and handled in workflow context, or otherwise use an explicitly designed non-retrying failure contract.
  • No cross-package src import or dependency-direction violation was found.

Change scope

Status: minimal

The implementation, regression test, falsy-value tracking, and patch changeset are all directly related to the reported bug.

Security

Risk: low

No code-execution, dependency, URL-handling, or package-boundary security issue is introduced, though thrown error messages can enter workflow failure records.

Testing

Status: needs-more

Node and edge unit tests cover direct Error and falsy rejection, but they bypass the workflow runtime behavior that makes the implementation unsafe.

Concerns:

  • Add an @workflow/vitest regression test that executes WorkflowAgent through a real workflow and verifies no model-step retry and preservation of the intended terminal classification.
  • Add coverage asserting that onError is invoked exactly once for a standard stream error part.

Verification

Inspected the complete four-file diff and relevant workflow runtime implementation. The new node and edge regression tests passed, 130 related node tests passed, package type checking passed, and a direct probe confirmed falsy rejection but found duplicate onError calls. The repository workflow integration suite could not execute because of an unrelated workflow-runtime setup failure. Official workflow documentation and runtime code confirm that thrown step errors retry by default and are normalized before reaching workflow context.

Relevant Documentation

ai-sdk-factory and others added 2 commits August 14, 2026 22:48
Co-authored-by: MintedKenny <104696466+MintedKenny@users.noreply.github.com>
Co-authored-by: ai-sdk-factory[bot] <305873210+ai-sdk-factory[bot]@users.noreply.github.com>
Co-authored-by: Gregor Martynus <39992+gr2m@users.noreply.github.com>
@ai-sdk-factory ai-sdk-factory Bot changed the title fix: surface model stream error values as WorkflowAgent terminal failures fix: surface WorkflowAgent model stream error values without durable-step retries or duplicate callbacks Aug 14, 2026
@ai-sdk-factory

Copy link
Copy Markdown
Contributor Author

Addressed PR comment 5285148791.

Bugfix review

Outcome: changes-required

Reproduction replay

Status: no-longer-reproduces

... 88 more line(s) omitted

Changed the durable-step contract so doStreamStep forwards the error part and returns its value as terminal data instead of throwing inside use step; the iterator now throws it in workflow context, avoiding automatic model-step retries and workflow failure normalization. Removed the iterator-level onError wiring from WorkflowAgent so the outer agent handler invokes the callback exactly once, while explicit presence tracking preserves falsy thrown values. Added an @workflow/vitest regression that verifies a serializable structured classification crosses the real step boundary with one streamed error part and one callback invocation. Direct tests continue to cover Error identity and falsy values outside serialization. The focused tests, durable integration suite, full repository tests, type checks, and repository checks now pass.

@ai-sdk-factory

Copy link
Copy Markdown
Contributor Author

Bugfix review

Outcome: changes-required

Reproduction replay

Status: no-longer-reproduces

The exact original reproduction completed successfully and the original bug signal did not appear.

Fixes issue

Status: fully-addresses

The error part is forwarded, returned across the durable step boundary as terminal data, and then thrown in workflow context; falsy values are retained and onError is invoked once.

Side effects

Risk: medium

The change deliberately converts a previously resolved error-finish path into a rejected WorkflowAgent.stream call.

Concerns:

  • Existing consumers that inspect finishReason="error" on a resolved result will instead enter their rejection path.

Performance

Risk: none

Returning terminal data avoids durable-step retries and stops consuming the stream after the terminal error, with no unbounded allocation or repeated model request.

Backwards compatibility

Risk: none

Existing stored workflow data is not rewritten or migrated; new runs persist the terminal value as an internal step-result variant.

Breaking changes

Risk: medium

WorkflowAgent.stream now rejects for a standard model error part where the published behavior previously resolved with an error finish reason.

Concerns:

  • This is a newly thrown public error behavior and requires existing resolved-result consumers to add rejection handling.
  • The PR describes the behavior as a patch without documenting migration or using the issue's backward-compatible alternative of an explicit terminal field on the result.

Architecture

Risk: none

The terminal value crosses the retryable step as persisted data and is thrown only in workflow context, matching durable workflow boundaries and preserving package dependency direction.

Change scope

Status: minimal

The implementation, callback adjustment, durable mock support, regression tests, integration workflow, and patch changeset are directly related to fixing and verifying the reported behavior.

Security

Risk: low

No dependency, code-execution, URL-handling, or package-boundary risk was introduced; the supplied error value is now additionally stored as durable step data.

Testing

Status: appropriate

Tests cover direct Error identity, falsy terminal values, forwarding, exactly one callback, and a real durable workflow proving structured classification and one streamed error without retries.

Verification

Inspected the complete merge-base diff, public exports and result types, workflow serialization and retry behavior, and package boundaries. The workflow package's node and edge suites each passed 177 tests, the durable integration suite passed 20 tests including the new regression, package type checking passed, and focused serialization checks confirmed Error, structured-object, falsy, and undefined terminal values cross the step boundary.

Relevant Documentation

@gr2m

gr2m commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Addressed the remaining backwards-compatibility concern in 4f59cea. WorkflowAgent no longer rejects for a standard model stream error part; it keeps the existing resolved finishReason: "error" behavior and exposes the original value on the additive result.error field. The value still crosses the durable step boundary as data, onError fires once, falsy/undefined values are preserved, and the public reference plus changeset were updated.

Verification: 178 Node tests, 178 Edge tests, 20 durable integration tests, full repository type-check, and repository lint/format all pass.

@gr2m gr2m left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the backward-compatible result contract, durable error transport, callback behavior, regression coverage, and full CI results. All concerns are addressed.

@gr2m
gr2m merged commit 83f9b12 into main Aug 18, 2026
51 checks passed
@gr2m
gr2m deleted the bugfix-18824-20260813145943955344 branch August 18, 2026 05:48
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Published in:

Package Version
ai 7.0.67 github npm
@ai-sdk/angular 3.0.67 github npm
@ai-sdk/code-mode 1.0.24 github npm
@ai-sdk/gateway 4.0.53 github npm
@ai-sdk/google 4.0.45 github npm
@ai-sdk/google-vertex 5.0.56 github npm
@ai-sdk/harness 1.0.74 github npm
@ai-sdk/harness-acp 1.0.12 github npm
@ai-sdk/harness-claude-code 1.0.77 github npm
@ai-sdk/harness-cline 1.0.2 github npm
@ai-sdk/harness-codex 1.0.76 github npm
@ai-sdk/harness-deepagents 1.0.74 github npm
@ai-sdk/harness-grok-build 1.0.11 github npm
@ai-sdk/harness-opencode 1.0.75 github npm
@ai-sdk/harness-pi 1.0.76 github npm
@ai-sdk/langchain 3.0.67 github npm
@ai-sdk/llamaindex 3.0.67 github npm
@ai-sdk/otel 1.0.67 github npm
@ai-sdk/policy-opa 1.0.67 github npm
@ai-sdk/react 4.0.70 github npm
@ai-sdk/rsc 3.0.67 github npm
@ai-sdk/sandbox-just-bash 1.0.74 github npm
@ai-sdk/sandbox-vercel 1.0.74 github npm
@ai-sdk/svelte 5.0.67 github npm
@ai-sdk/tui 1.0.68 github npm
@ai-sdk/vue 4.0.67 github npm
@ai-sdk/workflow 1.0.68 github npm
@ai-sdk/workflow-harness 1.0.74 github npm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WorkflowAgent does not surface the value of standard stream error parts as terminal failure

2 participants