{"record":{"id":"382ec8b870b69d03","repo":"mastra-ai/mastra","slug":"factory-kickoff-run-ended-in-error","errorCode":null,"errorMessage":"Factory kickoff run ended in error.","messagePattern":"Factory kickoff run ended in error\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/factory/src/rules/dispatcher.ts","lineNumber":994,"sourceCode":"              // \"processed\" signal, so wait for the in-flight run to end and\n              // redeliver into the idle session unconditionally — the\n              // generation-scoped dedupeKey defeats inbox dedupe and the\n              // kickoff key keeps a duplicate run bounded, while a dropped\n              // kickoff strands the card forever.\n              if (!(await waitForAgentEndOrTimeout(agentEnd, this.#skillCompletionObservationTimeoutMs))) {\n                throw new Error('Factory kickoff is waiting on a run that has not ended.');\n              }\n              armAgentEnd();\n              settled = await sendKickoff(`factory-kickoff:${record.kickoffKey}:retry:${record.attempts}`);\n              if (settled?.action !== 'wake') {\n                throw new Error('Factory kickoff was queued onto an ending run and never reached the agent.');\n              }\n            }\n            const observed = await waitForAgentEndOrTimeout(agentEnd, this.#skillCompletionObservationTimeoutMs);\n            if (!observed) {\n              throw new Error('Factory kickoff run terminal event was not observed before timeout.');\n            } else if (endReason === 'error') {\n              throw new Error('Factory kickoff run ended in error.');\n            } else if (endReason === 'aborted') {\n              // Retryable for the same reason as skill decisions: the dominant\n              // cause is the process going away underneath the run, not a\n              // deliberate stop, and a spurious retry is bounded by\n              // MAX_ATTEMPTS while a dead card costs a human a manual nudge.\n              throw new Error('Factory kickoff run was aborted before it finished.');\n            }\n          } finally {\n            unsubscribe();\n          }\n        },\n      );\n      const completed = await this.#storage.completePendingStart(leaseIdentity(record, this.#ownerId), new Date());\n      if (!completed) throw new Error('Factory kickoff lease was lost before completion.');\n    } catch (error) {\n      await this.#storage.failPendingStart({\n        ...leaseIdentity(record, this.#ownerId),\n        now: new Date(),","sourceCodeStart":976,"sourceCodeEnd":1012,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/factory/src/rules/dispatcher.ts#L976-L1012","documentation":"The kickoff run completed but its recorded endReason was 'error', meaning the agent run itself failed. The dispatcher surfaces this as a throw so the pending start is marked failed and retried with backoff, keeping the Factory card alive instead of silently consuming the kickoff. It distinguishes genuine run failure from timeout/abort cases so operators can diagnose the underlying agent error.","triggerScenarios":"The agent run started from the Factory kickoff terminated with endReason === 'error' — model API failure, tool exception, invalid input to the agent, or an unhandled error in the run pipeline.","commonSituations":"Model provider outages or rate limits during the run; a tool invoked by the agent threw; malformed work-item content fed to the agent; misconfigured model credentials (note the dispatcher primes credentials from startedBy before starting).","solutions":["Inspect the agent run's error details/traces to find the root cause before assuming dispatcher problems.","Verify credentials for the session owner (startedBy) are valid — primed credentials may be expired/revoked.","Confirm model availability and rate limits with your provider.","Let the retry deliver a fresh kickoff; if errors persist, fix the underlying tool/input error the run keeps hitting."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// verify credentials and provider health before kickoff\nawait primeCredentials({ orgId, userId: startedBy });\nconst healthy = await checkModelProviderHealth(modelId);\nif (!healthy) throw new Error('model provider unavailable; defer kickoff');","typeGuard":null,"tryCatchPattern":"try {\n  await dispatcher.dispatch(record);\n} catch (e) {\n  if (String(e?.message).includes('ended in error')) {\n    const cause = await fetchLastRunError(record); // inspect agent run traces\n    await fixOrRequeue(record, cause);\n  } else throw e;\n}","preventionTips":["Validate model credentials for the session owner before dispatch","Monitor provider status/rate limits for models used in Factory runs","Validate work-item inputs that feed agent prompts","Always inspect the underlying run error before requeueing"],"tags":["factory","agent-run","error-propagation","retry"],"backgroundTag":"agent-run-ended-in-error","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}