paperclipai/paperclip · error · NativeProviderTerminalFailure

provider_turn_failed

provider_turn_failed

Error message

provider_turn_failed

What it means

A provider turn failed terminally and the runtime throws NativeProviderTerminalFailure. The code is the provider-supplied failure code when it is a string, otherwise the generic 'provider_turn_failed'. The runtime separately detects model-rejection text and rewrites the failure as native_provider_model_rejected; recoverable failures are not turned terminal.

Source

Thrown at packages/paperclip-runner/src/native-session-runtime.ts:2367

            const failure =
              payload.error && typeof payload.error === "object"
                ? (payload.error as Record<string, unknown>)
                : payload;
            const message =
              typeof failure.message === "string"
                ? failure.message.slice(0, 2_000)
                : "Provider turn failed";
            const recoverable =
              failure.recoverable === true || payload.recoverable === true;
            // Retain the older consumer's permanent-model classification while
            // preserving structured provider metadata. A provider explicitly
            // permitting retry must not become permanent merely from its text.
            const modelRejected =
              !recoverable &&
              /issue with the selected model|model_not_found|invalid model|model[^\n]*(?:does not exist|not found|not supported)/i.test(
                message,
              );
            throw new NativeProviderTerminalFailure(
              typeof failure.code === "string"
                ? failure.code
                : "provider_turn_failed",
              recoverable,
              modelRejected
                ? `native_provider_model_rejected: ${message}`
                : message,
            );
          }
          if (settledCompletion === null && options.resolveMissingResult) {
            const recoveredResult = await options.resolveMissingResult({
              turnId: terminalEvent.turnId ?? null,
              terminalEvent,
            });
            signal.throwIfAborted();
            if (recoveredResult !== null) {
              settledCompletion = {
                result: recoveredResult,

View on GitHub (pinned to 01ad858492)

Solutions

  1. Inspect the failure message for the real provider-side cause
  2. Retry the run — if the failure was actually transient, this was misclassified as terminal
  3. Check provider status/region outages and API version compatibility
  4. Upgrade the runtime/provider adapter so failure codes are surfaced as strings
Defensive patterns

Strategy: retry

Validate before calling

// validate provider response has a code before treating as terminal
if (failure && typeof failure.code !== 'string' && !failure.message) logWarning('unclassified provider failure');

Type guard

const hasCode = (f) => !!f && typeof f.code === 'string';

Try / catch

try { await providerTurn() } catch (e) { if (e instanceof NativeProviderTerminalFailure && e.recoverable) retry(); else throw e; }

Prevention

When it happens

Trigger: Calling a provider turn where the provider returns a failure with no string code and the message does not match the model-rejection regex, and the failure is not recoverable.

Common situations: Provider API errors without structured codes (HTML error pages, truncated responses); transient-but-unrecoverable provider outages; malformed provider stream.

Related errors


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/73f88a7617b44a41. Report an issue: GitHub.