Skip to content

runtime: transport failures wrapped as "Cannot connect to API" are never retried; the classifier ignores the AI SDK isRetryable flag and the error cause #3756

Description

@jsiu93

What happened

The provider transport failed with this complete captured line:

maka run: Cannot connect to API: 80E1BDF601000000:error:0A000119:SSL routines:tls_get_more_records:decryption failed or bad record mac:../deps/openssl/openssl/ssl/record/methods/tls_common.c:869:

On my machine this ended the maka run turn on the first attempt with exit code 1. The same carrier shape is still terminal on main at d92d277.

The sibling gap for status-less server_error 502 streams was closed by #3515. This issue is limited to the wrapped transport failure. Bare 429 responses are deliberately terminal without a valid retry delay since #3115 and are not part of this issue.

How to reproduce

  1. Configure an AI SDK provider call through maka run.
  2. Make the underlying fetch fail with a TLS cause whose message contains decryption failed or bad record mac.
  3. Let the AI SDK wrap it as Cannot connect to API: ${cause.message}.
  4. Observe that the turn emits the terminal error and exits with code 1 without a provider retry.

Expected

A transport failure that the AI SDK marks retryable should enter Maka's bounded provider retry policy, subject to the existing no-observable-output and step-budget gates. The turn should remain active while an eligible retry is pending.

Root cause

The AI SDK creates an APICallError with Cannot connect to API: ${cause.message} and sets isRetryable: true (node_modules/@ai-sdk/provider-utils/src/handle-fetch-error.ts:52, node_modules/@ai-sdk/provider-utils/src/handle-fetch-error.ts:56, v0.1.11 tree).

Maka's providerRetryMetadata normalizes the top-level provider error but does not honor APICallError.isRetryable or walk cause (packages/runtime/src/provider-error-classification.ts:173, packages/runtime/src/provider-error-classification.ts:223, main). The main classifier only recognizes text-only network failures containing network, fetch, or typeerror ... terminated (packages/runtime/src/provider-error-classification.ts:697, packages/runtime/src/provider-error-classification.ts:698, packages/runtime/src/provider-error-classification.ts:699). The observed message contains none of those tokens, so classification falls through to the error name and maps to Other (packages/runtime/src/provider-error-classification.ts:702).

The v0.1.11 tree already allowed 10 provider attempts per step (packages/runtime/src/ai-sdk-backend.ts:913), and main keeps the cap at 10 (packages/runtime/src/ai-sdk-backend.ts:912). The failure never reaches that loop because failure.retryable is false. Main still gates retries on retryability, attempt count, remaining step budget, and no observable output (packages/runtime/src/ai-sdk-backend.ts:2495, packages/runtime/src/ai-sdk-backend.ts:2497, packages/runtime/src/ai-sdk-backend.ts:2498, packages/runtime/src/ai-sdk-backend.ts:2499).

For comparison, main now recognizes server_error as a status-less provider-unavailable code (packages/runtime/src/provider-error-classification.ts:36, packages/runtime/src/provider-error-classification.ts:686) and has a regression case with the observed 502 wording (packages/runtime/src/__tests__/provider-error-classification.test.ts:229). Bare RateLimit or 429 remains terminal when no valid delay is present (packages/runtime/src/provider-error-classification.ts:191, packages/runtime/src/provider-error-classification.ts:192); the changelog attributes that rate-limit hardening to #3115 (CHANGELOG.md:53).

Proposed boundary

  1. Honor APICallError.isRetryable, or walk cause, as a retry signal in providerRetryMetadata.
  2. Add the exact TLS message to provider-error-classification.test.ts next to the 502 case at main line 229.
  3. Keep the existing safe-output and 10-attempt gates unchanged.

Environment

  • macOS, Darwin 25.6.0, arm64.
  • Observed CLI: maka-agent@next 0.1.0-beta.1 on Node.js 22.22.2.
  • Current-main check: d92d277.
  • Surface: maka run.
  • Task: a macOS SwiftUI debugging task.

I will follow up with a PR for the classifier change.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinghelp wantedExtra attention is needed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions