mastra-ai/mastra · error

crossProcessPubSub requires a pubsub instance

Error message

crossProcessPubSub requires a pubsub instance

What it means

createMastraCodeAgentController() computes crossProcessPubSub from config.crossProcessPubSub or from enabling unix-socket pubsub when no pubsub was configured. Cross-process signaling requires an actual pubsub instance; if the flag is enabled but signalsPubSub is undefined (no config.pubsub and unix-socket path unavailable, e.g. on win32), the controller refuses to start.

Source

Thrown at mastracode/sdk/src/index.ts:507

  const resourceIdOverride = getResourceIdOverride(project.rootPath, configDir);
  if (resourceIdOverride) {
    project.resourceId = resourceIdOverride;
    project.resourceIdOverride = true;
  }

  // Stable session id unique to this project/resource, and a machine-bound owner
  // id. resourceId encodes root path + git identity and honors overrides, so it
  // is the right input for scoping the session to the cwd/project.
  const sessionId = `mastracode-session-${shortHash(project.resourceId)}`;
  const ownerId = `mastracode-${shortHash(`${hostname()}\0${project.rootPath}`)}`;

  const configuredPubSub = config?.pubsub;
  const useUnixSocketPubSub =
    (config?.unixSocketPubSub ?? globalSettings.signals?.unixSocketPubSub ?? false) && process.platform !== 'win32';
  const signalsPubSub = configuredPubSub ?? (useUnixSocketPubSub ? createSignalsPubSub(project.resourceId) : undefined);
  const crossProcessPubSub = config?.crossProcessPubSub ?? (!configuredPubSub && useUnixSocketPubSub);
  if (crossProcessPubSub && !signalsPubSub) {
    throw new Error('crossProcessPubSub requires a pubsub instance');
  }

  // Storage. An injected instance is used as-is — no connection test, no
  // LibSQL fallback: if the injected store fails, that's a hard error.
  const injectedStorage = isInjectedStorageInstance(config?.storage) ? config.storage : undefined;
  const storageConfig = injectedStorage
    ? undefined
    : ((config?.storage as StorageConfig | undefined) ??
      getStorageConfig(project.rootPath, globalSettings.storage, configDir));
  const storageResult: StorageResult = injectedStorage
    ? { storage: injectedStorage, backend: resolveInjectedStorageBackend(injectedStorage, config?.storageBackend) }
    : await createStorage(storageConfig!);
  const storageWarning = storageResult.warning;

  // Observability storage (DuckDB — separate file for OLAP-style trace/score/feedback queries).
  // Local tracing is opt-in via `/observability local on`. When disabled, the
  // MastraStorageExporter is omitted entirely so traces never fall through to
  // the default libsql backend.

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Provide an explicit instance: createMastraCodeAgentController({ crossProcessPubSub: true, pubsub: myPubSub }).
  2. Remove crossProcessPubSub/unixSocketPubSub if you only need single-process signaling.
  3. On Windows, switch to a platform-agnostic pubsub implementation instead of unixSocketPubSub.

Example fix

// before
createMastraCodeAgentController({ crossProcessPubSub: true });
// after
createMastraCodeAgentController({ crossProcessPubSub: true, pubsub: createMyPubSub() });
Defensive patterns

Strategy: validation

Validate before calling

const wantsCrossProcess = config?.crossProcessPubSub || config?.unixSocketPubSub;
if (wantsCrossProcess && !config?.pubsub && process.platform === 'win32') {
  throw new Error('crossProcessPubSub requires an explicit pubsub instance on this platform');
}

Type guard

function hasPubSub(c: unknown): c is { pubsub: NonNullable<MastraCodeConfig['pubsub']> } {
  return c != null && typeof c === 'object' && 'pubsub' in c && c.pubsub != null;
}

Try / catch

try {
  controller = await createMastraCodeAgentController(cfg);
} catch (err) {
  if (err instanceof Error && err.message.includes('crossProcessPubSub requires a pubsub instance')) {
    controller = await createMastraCodeAgentController({ ...cfg, pubsub: createDefaultPubSub() });
  } else { throw err; }
}

Prevention

When it happens

Trigger: Setting config.crossProcessPubSub: true without config.pubsub; or setting unixSocketPubSub: true while process.platform === 'win32' (the useUnixSocketPubSub guard disables socket creation, leaving signalsPubSub undefined).

Common situations: Copy-pasting a Unix-only multi-process config onto Windows; enabling crossProcessPubSub in a config file without wiring a pubsub implementation; forgetting that unixSocketPubSub alone does not create a pubsub on non-Unix platforms.

Related errors


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