Skip to content

fix(execution): classify SDK run aborts and refuse doomed provider and media requests before sending - #9211

Merged
waleedlatif1 merged 3 commits into
stagingfrom
fix/run-abort-and-media-tool-failures
Oct 19, 2026
Merged

waleedlatif1 merged 3 commits into
stagingfrom
fix/run-abort-and-media-tool-failures

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Stopped Agent runs no longer fail the block. The Anthropic, OpenAI and Groq SDKs throw APIUserAbortError with name === 'Error', so the name check ('AbortError', plus an 'APIUserAbortError' name check that could never match) missed every SDK abort. A user Stop therefore painted the Agent block failed and logged it at ERROR as internal. New isRunAbortError(error, signal) recognises the SDK classes by instanceof and treats the run's abort signal as the deciding fact: an abort-shaped error while the run is still live stays a real failure. BlockExecutor and runtime-context now use it.
  • A stopped Gemini/fetch-based Agent is no longer reported as "Provider request timed out". AgentBlockHandler.handleExecutionError rewrote any AbortError into a transport-timeout message marked third_party_server, user Stops included. A stopped run's abort now passes through unchanged. A run-timeout abort is still rewritten as before.
  • Provider catch logs use failure-log severities. providerFailureLogLevel: a user Stop logs at info, a run time limit at warn, a UserFailure at info, and everything else still at error. This applies to every provider's Error in X request catch and to OpenAI's transport-failure log.
  • Media tools check the output path before paying. generate_audio, generate_video and generate_image now validate an explicit output path (validateCopilotWorkspaceFileWriteTarget, the same check Function exports run) before calling the provider. Before, a path into a folder that had since moved was refused only at write time, after fal/Gemini had billed, and the model retried and paid again. The write still re-validates.
  • Gemini TTS rejects voices it does not have. fal's Gemini 3.1 Flash TTS accepts only its 30 prebuilt voices (list checked against fal's API docs and its own 422). Names from other providers (Brian, Liam, …) now fail before submitting, and the error lists the valid voices. This builds on fix(media): send ElevenLabs TTS text under the field fal requires #9195.
  • Gemini with no user content fails clearly. It now throws EmptyProviderInputError (fix(providers): refuse an empty Responses input before sending instead of retrying a guaranteed 400 #9196's abstraction; the constructor takes an optional message) instead of the SDK's opaque contents are required. Gemini needs a user turn even when a system prompt is set. The error is nonretryable and attributed to the author.
  • Log noise: a file-archive download whose client disconnected no longer logs Failed to build file archive, because a closed archive is the deciding fact. Resume failures (manager, background job, poll dispatcher) now log once per attempt through logFailureOnce instead of three times.

Out of scope: Anthropic's empty-input behaviour (it injects a Hello user turn) is left unchanged. "Assistant message prefill" 400s on newer Claude models come from a conversation ending in an assistant turn. That happens either because the author configured it that way (prefill used to be a supported technique) or because history ends on an assistant turn and the new user turn is empty. Neither has a single correct fix, so this PR does not change it.

Type of Change

  • Bug fix

Testing

  • Each new test was run against the pre-fix code to confirm it fails there:
    • block-executor.test.ts: real Anthropic/OpenAI/Groq SDK requests (a fetch that only rejects on cancel). A user Stop soft-completes, a run timeout fails the block attributed to user, and a request cancelled while the run is live fails as internal. Red against the old name check, against the SDK classes removed, and against the signal guard removed.
    • providers/anthropic/core.test.ts: real SDK client. A Stop logs at info, a run timeout at warn, a genuine 500 at error.
    • handler.test.ts: a stopped run's abort passes through unrewritten, and a run timeout is still reported as a provider timeout.
    • write-target-precheck.integration.ts (real Postgres): for audio, video and image, a moved-folder target is refused without calling the provider and without recording a cost. A target at the folder's current path still generates and writes.
    • falai.test.ts: an unsupported Gemini TTS voice is refused with nothing submitted.
    • gemini/core.test.ts: real GoogleGenAI. System-only and all-empty requests now raise EmptyProviderInputError instead of contents are required.
    • archive-presenter.test.ts: a disconnect that tears down storage with Node's bare aborted no longer logs, and a failure with the client still connected still logs.
    • resume-execution.test.ts: a failure the resume manager already logged is not logged again.
  • Targeted vitest runs over the changed areas pass (providers, executor, mothership tools, media, resume, archive). bun run lint passes, and so do check:test-patterns, comment-hygiene, utils, explicit-any, source-conventions, boundaries, client-boundary and unused-exports.
  • A narrow tsc over the changed files reports the same diagnostics before and after (no new type errors in the test files). Full type-check and audits are left to CI.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing (new tests pass the test-audit authoring gate)
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

…d media requests before sending

- Recognise the Anthropic, OpenAI and Groq SDKs' APIUserAbortError (name 'Error') as an abort,
  with the run's abort signal deciding whether a failure is the run's own Stop or time limit
- Agent blocks a user stopped soft-complete again instead of failing; the agent handler no
  longer rewrites a stopped run's abort into "Provider request timed out"
- Provider catch logs: a user Stop at info, a run timeout at warn, an author fault at info,
  everything else still at error
- Media tools (audio, video, image) validate an explicit output path before generating, so a
  stale moved-folder path no longer bills a generation it then cannot save
- Gemini TTS refuses a voice it does not offer before submitting, listing the valid voices
- Gemini refuses a request with no user content as EmptyProviderInputError instead of the
  SDK's opaque "contents are required"
- File archive downloads no longer log a client disconnect as a failure; resume failures log
  once per attempt through logFailureOnce
@vercel

vercel Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
docs Ready Ready Preview Oct 19, 2026 12:14am UTC

Request Review

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 42 files

Reply with feedback, questions, or to request a fix.

Turn on auto-fix | Re-trigger cubic

Comment thread apps/sim/lib/workflows/executor/human-in-the-loop-manager.ts Outdated
Comment thread apps/sim/lib/workflows/executor/human-in-the-loop-manager.ts
Comment thread apps/sim/app/api/resume/poll/route.ts Outdated
Comment thread apps/sim/lib/workspace-files/api/archive-presenter.ts
Comment thread apps/sim/background/resume-execution.ts Outdated
@greptile-apps

greptile-apps Bot commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[High impact] The changes since the previous review appear safe to merge.

Summary

The PR separates stopped Agent runs from provider failures and rejects invalid media requests before sending them.

  • Agent stops finish cleanly while real request failures stay failures.
  • Provider request logs match the kind of failure they report.
  • Media tools check output paths before calling paid providers.
  • Gemini TTS rejects voice names its provider does not support.
  • Gemini explains when an Agent has no user content to send.
  • Resume and archive logs skip failures already explained by the run or disconnect.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Provider request fails] --> B{Run aborted and error matches?}
  B -->|No| C[Keep real failure]
  B -->|Yes| D{Run timed out?}
  D -->|Yes| E[Keep failed outcome]
  D -->|No| F[Stopped Agent returns partial or empty output]
  G[Media request with explicit output path] --> H{Write target allowed?}
  H -->|No| I[Refuse before generation]
  H -->|Yes| J[Generate media]
  J --> K[Check target again and write]
Loading

Reviews (3) · Last reviewed commit: "fix(resume): type the resume-failed mock..." · Reviewed by Greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 18, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No issues found across 42 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Turn on auto-fix | Re-trigger cubic

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 19, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No issues found across 43 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Turn on auto-fix | Re-trigger cubic

@waleedlatif1
waleedlatif1 merged commit bd44d7b into staging Oct 19, 2026
53 checks passed
@waleedlatif1
waleedlatif1 deleted the fix/run-abort-and-media-tool-failures branch October 19, 2026 03:21

This branch was successfully deployed

1 active deployment
Preview — a33f549c Deployed Oct 19, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant