mastra-ai/mastra · error

resourceId and threadId are required to send a state signal

Error message

resourceId and threadId are required to send a state signal

What it means

AgentThreadStreamRuntime.sendStateSignal() throws this when target.resourceId or target.threadId is missing. Unlike queueMessage, sendStateSignal performs no inference from active run records — the caller must supply both IDs up front so the state signal can be persisted to the correct memory thread.

Solutions

  1. Pass both resourceId and threadId in the target options before calling sendStateSignal.
  2. Add a pre-call guard that asserts both IDs are non-empty strings.
  3. If the IDs come from a request/session object, validate them at the API boundary instead of at signal time.

Example fix

// before
await runtime.sendStateSignal(agent, state, {});
// after
await runtime.sendStateSignal(agent, state, { resourceId: 'user-1', threadId: 'thread-1' });
Defensive patterns

Strategy: validation

Validate before calling

if (!target?.resourceId || !target?.threadId) {
  throw new Error('sendStateSignal requires resourceId and threadId');
}

Type guard

function isStateSignalTarget<T>(t: SendAgentStateSignalOptions<T>): t is SendAgentStateSignalOptions<T> & { resourceId: string; threadId: string } {
  return Boolean(t.resourceId && t.threadId);
}

Try / catch

try {
  return await runtime.sendStateSignal(agent, state, target);
} catch (e) {
  if (e instanceof Error && e.message.includes('required to send a state signal')) {
    // surface a 400-style validation error to the caller
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling runtime.sendStateSignal(agent, stateInput, target) with resourceId or threadId undefined/null in the SendAgentStateSignalOptions target.

Common situations: Partially constructed options objects when routing signals dynamically; type-looseness letting { resourceId } without threadId compile; migrating code that previously targeted an active run by runId only.

Related errors


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

Appendix: source

Thrown at packages/core/src/agent/thread-stream-runtime.ts:2707

      };
    }

    return this.sendSignal<OUTPUT>(
      agent,
      signal,
      { ...target, runId, resourceId, threadId, ifIdle: { ...target.ifIdle, behavior: 'wake' } },
      pubsub,
    );
  }

  async sendStateSignal<OUTPUT = unknown>(
    agent: Agent<any, any, any, any>,
    stateInput: AgentStateSignalInput,
    target: SendAgentStateSignalOptions<OUTPUT>,
    pubsub?: PubSub,
  ): Promise<SendAgentStateSignalResult<OUTPUT>> {
    if (!target.resourceId || !target.threadId) {
      throw new Error('resourceId and threadId are required to send a state signal');
    }
    const resourceId = target.resourceId;
    const threadId = target.threadId;

    const requestContext = target.ifIdle?.streamOptions?.requestContext;
    const memoryContext = parseMemoryRequestContext(requestContext);
    const memory = await agent.getMemory({ requestContext });
    if (!memory) {
      throw new Error('sendStateSignal requires Mastra memory');
    }

    const loadedThread = (await memory.getThreadById({ threadId })) ?? memoryContext?.thread;
    if (!loadedThread) {
      throw new Error(`sendStateSignal could not load thread ${threadId}`);
    }

    const thread = {
      ...loadedThread,

View on GitHub (pinned to 75dd419e61)