{"record":{"id":"744ff18cb3c374f4","repo":"thedotmack/claude-mem","slug":"sdk-turn-failed-before-emitting-text-re-queueing-the-claimed","errorCode":null,"errorMessage":"SDK turn failed before emitting text, re-queueing the claimed batch","messagePattern":"SDK turn failed before emitting text, re-queueing the claimed batch","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/services/worker/ClaudeProvider.ts","lineNumber":549,"sourceCode":"                  : undefined,\n            });\n          }\n\n          const resultSubtype = (message as any).subtype as string | undefined;\n          const resultIsError = (message as any).is_error === true || resultSubtype !== 'success';\n\n          // The turn is over and the model never emitted text. Only a\n          // successful turn means \"the model read the batch and chose to skip\n          // it\" — forward the empty response once so the claim is acknowledged\n          // instead of being retried forever. A failed turn never reached that\n          // judgement, so its batch goes back to the buffer for the drain to\n          // re-yield. Exactly one such retry per generator pass: a message is\n          // always pending while a batch is re-queued, so the buffer never\n          // idles out, and an endlessly failing turn would spin on it.\n          if (!turnDispatchedText) {\n            if (resultIsError && !retriedAfterErrorResult) {\n              retriedAfterErrorResult = true;\n              logger.warn('SDK', 'SDK turn failed before emitting text, re-queueing the claimed batch', {\n                sessionId: session.sessionDbId,\n                subtype: resultSubtype,\n              });\n              await this.sessionManager.resetProcessingToPending(session.sessionDbId);\n            } else {\n              await processAgentResponse(\n                '',\n                session,\n                this.dbManager,\n                this.sessionManager,\n                worker,\n                (session.cumulativeInputTokens + session.cumulativeOutputTokens) - discoveryTokenBaseline,\n                session.earliestPendingTimestamp,\n                'SDK',\n                cwdTracker.lastCwd,\n                modelId,\n                activeResponseContext.current\n              );","sourceCodeStart":531,"sourceCodeEnd":567,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/services/worker/ClaudeProvider.ts#L531-L567","documentation":"Logged when an SDK turn completes with an error result subtype before any text was dispatched, so the claimed message batch is re-queued to pending instead of being dropped. Exactly one such retry happens per generator pass to avoid an endless failing turn spinning on the buffer.","triggerScenarios":"In startSession's result handling, when resultIsError is true, turnDispatchedText is false, and retriedAfterErrorResult is false (first occurrence); resetProcessingToPending puts the claimed batch back in the queue.","commonSituations":"Transient SDK/CLI failures (crash, bad API response) on the very first turn of a batch; overloaded Claude API returning error results; a malformed prompt that fails before any assistant output.","solutions":["Inspect resultSubtype in the log to identify the underlying SDK failure and fix its root cause.","Retry the session after the transient condition clears; the batch is already back to pending.","If failures persist, check Claude SDK/CLI version compatibility and network/API status.","Remember only one automatic retry happens per pass — a second failing turn is processed as an error, not re-queued."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await provider.startSession(session);\n} catch (e) {\n  // batch was already reset to pending; re-poll the queue instead of discarding\n  await sessionManager.pollPending(session.sessionDbId);\n}","preventionTips":["Keep the Claude SDK/CLI version current","Monitor resultSubtype warnings for recurring failure causes","Avoid oversized first prompts that can fail before any text is emitted"],"tags":["retry","sdk-error","queue"],"backgroundTag":"api-request-failed","analyzedSha":"d8bc9755e74915e5c3b999181e10a67c889bce2a","analyzedAt":"2026-09-17T16:40:26.182Z","contentChangedAt":"2026-09-17T16:40:26.182Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}