mastra-ai/mastra · error

state signal id is required

Error message

state signal id is required

What it means

createStateSignalInput builds a state signal from input plus optional defaults. A state signal must have an id (identity for tracking across turns); if neither `input.id` nor `options.defaultId` provides one, this error is thrown before any signal is created.

Source

Thrown at packages/core/src/agent/state-signals.ts:204

  return {
    ...deriveStateSignalHistory(resolvedStateSignals.length > 0 ? resolvedStateSignals : localStateSignals),
    contextWindow,
  };
}

export function createStateSignalInput(
  input: AgentStateSignalInput | (Omit<AgentStateSignalInput, 'id'> & { id?: string }),
  options?: { defaultId?: string; acceptedAt?: Date },
): {
  stateId: string;
  signal: Extract<CreatedAgentSignal, { type: 'state' }>;
  mode: 'snapshot' | 'delta';
  cacheKey: string;
} {
  const stateId = input.id ?? options?.defaultId;
  if (!stateId) {
    throw new Error('state signal id is required');
  }
  if (!input.cacheKey) {
    throw new Error('state signal cacheKey is required');
  }

  const mode = input.mode ?? 'snapshot';
  const { id: _stateId, cacheKey, mode: _mode, value, delta, metadata, ...signalInput } = input;
  const signal = createSignal({
    ...signalInput,
    type: 'state',
    tagName: signalInput.tagName ?? 'state',
    acceptedAt: options?.acceptedAt,
    metadata: {
      ...metadata,
      state: {
        ...(isPlainObject(metadata?.state) ? metadata.state : {}),
        id: stateId,
        cacheKey,

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Pass an explicit id: `createStateSignalInput({ id: 'doc-state', cacheKey: 'docs', value }, ...)`.
  2. Provide `options.defaultId` when the same logical state is reused across a turn/agent scope.
  3. Re-use a stable id for the same logical state so snapshot/delta tracking works; don't invent a new id per call.
  4. Log/validate input.id and options.defaultId upstream to catch undefined values early.

Example fix

// before
createStateSignalInput({ cacheKey: 'docs', value });
// after
createStateSignalInput({ id: 'doc-state', cacheKey: 'docs', value });
Defensive patterns

Strategy: validation

Validate before calling

if (!input.id && !options?.defaultId) {
  throw new TypeError('state signal requires input.id or options.defaultId');
}

Type guard

function hasStateId(input: { id?: string }, options?: { defaultId?: string }): boolean {
  return Boolean(input.id ?? options?.defaultId);
}

Try / catch

try {
  created = createStateSignalInput(input, options);
} catch (e) {
  if (e instanceof Error && e.message === 'state signal id is required') {
    created = createStateSignalInput({ ...input, id: crypto.randomUUID() }, options);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling createStateSignalInput without `id` on the input and without a `defaultId` in options — e.g. `createStateSignalInput({ cacheKey: 'docs', value })` with no options argument.

Common situations: Refactoring call sites that previously generated ids; assuming the library auto-generates an id; passing defaultId under the wrong options key so it's undefined at runtime.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/492dff0c2ef64f0b. Report an issue: GitHub.