{"record":{"id":"950b43ab80643a89","repo":"mastra-ai/mastra","slug":"state-signals-cannot-be-transient","errorCode":null,"errorMessage":"state signals cannot be transient","messagePattern":"state signals cannot be transient","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/agent/signals.ts","lineNumber":590,"sourceCode":"  if (!input || typeof input !== 'object' || Array.isArray(input)) return false;\n\n  const candidate = input as Partial<CreatedAgentSignal>;\n  return candidate.__isCreatedSignal === true;\n}\n\nexport function createSignal(\n  input: Extract<AgentSignalInput, { type: 'state' }>,\n): Extract<CreatedAgentSignal, { type: 'state' }>;\nexport function createSignal(\n  input: Extract<AgentSignalInput, { type: Exclude<AgentSignalType, 'state'> }>,\n): Extract<CreatedAgentSignal, { type: Exclude<AgentSignalCategory, 'state'> }>;\nexport function createSignal(input: AgentSignalInput): CreatedAgentSignal;\nexport function createSignal(input: AgentSignalInput): CreatedAgentSignal {\n  if (input.type === 'state' && input.transient !== undefined) {\n    // State signals maintain cross-turn tracking (version/cacheKey/activeCopies) that is\n    // rebuilt from persisted history — a delivery-only state signal would silently break\n    // dedupe and leave tracking pointing at messages that were never stored.\n    throw new Error('state signals cannot be transient');\n  }\n  const signal = normalizeSignal(input);\n  const parts = contentsToSignalParts(signal.contents);\n\n  const created = {\n    ...signal,\n    __isCreatedSignal: true as const,\n    toDBMessage: (options?: { threadId?: string; resourceId?: string }) => signalToDBMessage(signal, parts, options),\n    toLLMMessage: () => signalToLLMMessage(signal, parts),\n    toDataPart: () => signalToDataPart(signal, parts),\n  };\n\n  if (created.type === 'state') {\n    const { transient: _transient, ...stateSignal } = created;\n    return { ...stateSignal, type: created.type };\n  }\n\n  return { ...created, type: created.type };","sourceCodeStart":572,"sourceCodeEnd":608,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/agent/signals.ts#L572-L608","documentation":"State signals carry cross-turn tracking (version, cacheKey, activeCopies) that is rebuilt from persisted history. Marking a state signal `transient` (delivery-only, not persisted) would silently break that dedupe/tracking because the tracking would point at messages that were never stored. createSignal therefore rejects the combination up front.","triggerScenarios":"Calling createSignal (directly or via createStateSignalInput / signal helpers) with `{ type: 'state', transient: ... }` — including `transient: false` — which still counts as `transient !== undefined`.","commonSituations":"Copying a transient reactive-signal factory and changing only `type` to 'state'; spreading user-supplied options that happen to include a `transient` key; passing `transient: false` thinking it means 'not transient'.","solutions":["Remove the `transient` property entirely from state signal inputs (even `transient: false` triggers the error).","Omit the key when spreading: `const { transient: _t, ...rest } = input; createSignal({ ...rest, type: 'state' })`.","If you need delivery-only behavior, use a non-state signal type instead of state+transient.","Sanitize persisted/external payloads in mastraDBMessageToSignal / dataPartToSignal paths before reconstructing."],"exampleFix":"// before\ncreateSignal({ type: 'state', cacheKey: 'docs', transient: false, contents });\n// after\ncreateSignal({ type: 'state', cacheKey: 'docs', contents });","handlingStrategy":"validation","validationCode":"if (input.type === 'state' && 'transient' in input) {\n  throw new TypeError('state signals must not include a transient property');\n}","typeGuard":"type StateSignalInput = Omit<Extract<AgentSignalInput, { type: 'state' }>, 'transient'>;\nfunction isStateWithoutTransient(x: { type: string } & Record<string, unknown>): x is StateSignalInput {\n  return x.type === 'state' && !('transient' in x);\n}","tryCatchPattern":"try {\n  signal = createSignal(input);\n} catch (e) {\n  if (e instanceof Error && e.message === 'state signals cannot be transient') {\n    const { transient: _t, ...rest } = input;\n    signal = createSignal(rest);\n  } else throw e;\n}","preventionTips":["Never spread raw input objects into createSignal; destructure and drop `transient` for state signals","Remember `transient: false` still triggers the error — omit the key entirely","Model state-signal inputs with a type that omits `transient`"],"tags":["signals","invalid-combination","state"],"backgroundTag":"incompatible-option-combination","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}