{"record":{"id":"73f88a7617b44a41","repo":"paperclipai/paperclip","slug":"provider-turn-failed","errorCode":"provider_turn_failed","errorMessage":"provider_turn_failed","messagePattern":"provider_turn_failed","errorType":"error_code","errorClass":"NativeProviderTerminalFailure","httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/native-session-runtime.ts","lineNumber":2367,"sourceCode":"            const failure =\n              payload.error && typeof payload.error === \"object\"\n                ? (payload.error as Record<string, unknown>)\n                : payload;\n            const message =\n              typeof failure.message === \"string\"\n                ? failure.message.slice(0, 2_000)\n                : \"Provider turn failed\";\n            const recoverable =\n              failure.recoverable === true || payload.recoverable === true;\n            // Retain the older consumer's permanent-model classification while\n            // preserving structured provider metadata. A provider explicitly\n            // permitting retry must not become permanent merely from its text.\n            const modelRejected =\n              !recoverable &&\n              /issue with the selected model|model_not_found|invalid model|model[^\\n]*(?:does not exist|not found|not supported)/i.test(\n                message,\n              );\n            throw new NativeProviderTerminalFailure(\n              typeof failure.code === \"string\"\n                ? failure.code\n                : \"provider_turn_failed\",\n              recoverable,\n              modelRejected\n                ? `native_provider_model_rejected: ${message}`\n                : message,\n            );\n          }\n          if (settledCompletion === null && options.resolveMissingResult) {\n            const recoveredResult = await options.resolveMissingResult({\n              turnId: terminalEvent.turnId ?? null,\n              terminalEvent,\n            });\n            signal.throwIfAborted();\n            if (recoveredResult !== null) {\n              settledCompletion = {\n                result: recoveredResult,","sourceCodeStart":2349,"sourceCodeEnd":2385,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/native-session-runtime.ts#L2349-L2385","documentation":"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.","triggerScenarios":"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.","commonSituations":"Provider API errors without structured codes (HTML error pages, truncated responses); transient-but-unrecoverable provider outages; malformed provider stream.","solutions":["Inspect the failure message for the real provider-side cause","Retry the run — if the failure was actually transient, this was misclassified as terminal","Check provider status/region outages and API version compatibility","Upgrade the runtime/provider adapter so failure codes are surfaced as strings"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// validate provider response has a code before treating as terminal\nif (failure && typeof failure.code !== 'string' && !failure.message) logWarning('unclassified provider failure');","typeGuard":"const hasCode = (f) => !!f && typeof f.code === 'string';","tryCatchPattern":"try { await providerTurn() } catch (e) { if (e instanceof NativeProviderTerminalFailure && e.recoverable) retry(); else throw e; }","preventionTips":["Keep provider adapters updated so failure codes are surfaced as strings","Wrap turn calls in retry with backoff for recoverable failures","Alert on provider_turn_failed spikes to catch provider outages","Match provider error-message changes against the model-rejection regex when upgrading"],"tags":["provider","terminal-failure","streaming"],"backgroundTag":"upstream-api-error","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}