mastra-ai/mastra · error

state signal cacheKey is required

Error message

state signal cacheKey is required

What it means

A state signal's cacheKey is what links snapshots/deltas together across turns for versioning and dedupe. createStateSignalInput requires a non-empty cacheKey; an empty string or undefined throws this error right after the id check.

Source

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

    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,
        mode,
      },
      ...(value !== undefined ? { value } : {}),

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Supply a stable, non-empty cacheKey: `createStateSignalInput({ id: 'doc-state', cacheKey: 'docs:v1', value })`.
  2. Ensure the dynamic source of the cacheKey (entity id, resource id) is populated before the call.
  3. Check property-name typos (`cacheKey` is camelCase) in object literals.
  4. Add a pre-call check: `if (!input.cacheKey) throw ...` or default it from a known constant.

Example fix

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

Strategy: validation

Validate before calling

if (!input.cacheKey) {
  throw new TypeError('state signal requires a non-empty cacheKey');
}

Type guard

function hasCacheKey(input: { cacheKey?: string }): input is { cacheKey: string } {
  return typeof input.cacheKey === 'string' && input.cacheKey.length > 0;
}

Try / catch

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

Prevention

When it happens

Trigger: Calling createStateSignalInput where `input.cacheKey` is undefined or '' — e.g. building the input dynamically from a variable that is empty, or destructuring state-signal fields and dropping cacheKey.

Common situations: Dynamic cache keys derived from config or entity ids that end up empty; forgetting cacheKey when constructing inputs in tests; typos like `cachekey` leaving the real key undefined.

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/061ea16a18aea4e6. Report an issue: GitHub.