{"record":{"id":"605031c178e5a75a","repo":"mastra-ai/mastra","slug":"crossprocesspubsub-requires-a-pubsub-instance","errorCode":null,"errorMessage":"crossProcessPubSub requires a pubsub instance","messagePattern":"crossProcessPubSub requires a pubsub instance","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/sdk/src/index.ts","lineNumber":507,"sourceCode":"  const resourceIdOverride = getResourceIdOverride(project.rootPath, configDir);\n  if (resourceIdOverride) {\n    project.resourceId = resourceIdOverride;\n    project.resourceIdOverride = true;\n  }\n\n  // Stable session id unique to this project/resource, and a machine-bound owner\n  // id. resourceId encodes root path + git identity and honors overrides, so it\n  // is the right input for scoping the session to the cwd/project.\n  const sessionId = `mastracode-session-${shortHash(project.resourceId)}`;\n  const ownerId = `mastracode-${shortHash(`${hostname()}\\0${project.rootPath}`)}`;\n\n  const configuredPubSub = config?.pubsub;\n  const useUnixSocketPubSub =\n    (config?.unixSocketPubSub ?? globalSettings.signals?.unixSocketPubSub ?? false) && process.platform !== 'win32';\n  const signalsPubSub = configuredPubSub ?? (useUnixSocketPubSub ? createSignalsPubSub(project.resourceId) : undefined);\n  const crossProcessPubSub = config?.crossProcessPubSub ?? (!configuredPubSub && useUnixSocketPubSub);\n  if (crossProcessPubSub && !signalsPubSub) {\n    throw new Error('crossProcessPubSub requires a pubsub instance');\n  }\n\n  // Storage. An injected instance is used as-is — no connection test, no\n  // LibSQL fallback: if the injected store fails, that's a hard error.\n  const injectedStorage = isInjectedStorageInstance(config?.storage) ? config.storage : undefined;\n  const storageConfig = injectedStorage\n    ? undefined\n    : ((config?.storage as StorageConfig | undefined) ??\n      getStorageConfig(project.rootPath, globalSettings.storage, configDir));\n  const storageResult: StorageResult = injectedStorage\n    ? { storage: injectedStorage, backend: resolveInjectedStorageBackend(injectedStorage, config?.storageBackend) }\n    : await createStorage(storageConfig!);\n  const storageWarning = storageResult.warning;\n\n  // Observability storage (DuckDB — separate file for OLAP-style trace/score/feedback queries).\n  // Local tracing is opt-in via `/observability local on`. When disabled, the\n  // MastraStorageExporter is omitted entirely so traces never fall through to\n  // the default libsql backend.","sourceCodeStart":489,"sourceCodeEnd":525,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/sdk/src/index.ts#L489-L525","documentation":"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.","triggerScenarios":"Setting config.crossProcessPubSub: true without config.pubsub; or setting unixSocketPubSub: true while process.platform === 'win32' (the useUnixSocketPubSub guard disables socket creation, leaving signalsPubSub undefined).","commonSituations":"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.","solutions":["Provide an explicit instance: createMastraCodeAgentController({ crossProcessPubSub: true, pubsub: myPubSub }).","Remove crossProcessPubSub/unixSocketPubSub if you only need single-process signaling.","On Windows, switch to a platform-agnostic pubsub implementation instead of unixSocketPubSub."],"exampleFix":"// before\ncreateMastraCodeAgentController({ crossProcessPubSub: true });\n// after\ncreateMastraCodeAgentController({ crossProcessPubSub: true, pubsub: createMyPubSub() });","handlingStrategy":"validation","validationCode":"const wantsCrossProcess = config?.crossProcessPubSub || config?.unixSocketPubSub;\nif (wantsCrossProcess && !config?.pubsub && process.platform === 'win32') {\n  throw new Error('crossProcessPubSub requires an explicit pubsub instance on this platform');\n}","typeGuard":"function hasPubSub(c: unknown): c is { pubsub: NonNullable<MastraCodeConfig['pubsub']> } {\n  return c != null && typeof c === 'object' && 'pubsub' in c && c.pubsub != null;\n}","tryCatchPattern":"try {\n  controller = await createMastraCodeAgentController(cfg);\n} catch (err) {\n  if (err instanceof Error && err.message.includes('crossProcessPubSub requires a pubsub instance')) {\n    controller = await createMastraCodeAgentController({ ...cfg, pubsub: createDefaultPubSub() });\n  } else { throw err; }\n}","preventionTips":["Provide config.pubsub whenever crossProcessPubSub (or unixSocketPubSub) is enabled.","On Windows, use a TCP/named-pipe pubsub instead of unixSocketPubSub.","Gate cross-process options behind platform checks in shared config files."],"tags":["configuration","pubsub","signals"],"backgroundTag":"missing-pubsub-instance","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}