mastra-ai/mastra · error · Error

GitHub integration is required to load webhook subscriptions

Error message

GitHub integration is required to load webhook subscriptions.

What it means

dispatchGithubWebhook lists PR subscriptions via an injectable listSubscriptions dependency; when no override is supplied it falls back to listPullRequestSubscriptionsForWebhook, which requires dependencies.github.integrationStorage. If dependencies.github is absent, there is no storage to read subscriptions from, so the lazily-built closure throws with a clear message instead of an opaque undefined-access error.

Source

Thrown at mastracode/factory/src/integrations/github/webhook.ts:531

  const notification = classifyGithubWebhook(parsed);
  if (!notification) return { delivered: 0, failed: 0, skipped: 0, ignored: true };
  const isAuthorizedSender =
    dependencies.isAuthorizedSender ??
    ((n: GithubWebhookNotification) => isAuthorizedGithubSender(n, dependencies.github));
  if (!(await isAuthorizedSender(notification))) {
    dependencies.onSenderRejected?.(notification);
    return { delivered: 0, failed: 0, skipped: 0, ignored: true };
  }

  const target = {
    installationExternalId: notification.metadata.installationId.toString(),
    repositoryExternalId: notification.metadata.repositoryId.toString(),
    changeRequestId: notification.metadata.pullRequestNumber.toString(),
  };
  const listSubscriptions =
    dependencies.listSubscriptions ??
    ((subscriptionTarget: GithubWebhookPullRequestTarget, options?: { includeTerminal?: boolean }) => {
      if (!dependencies.github) throw new Error('GitHub integration is required to load webhook subscriptions.');
      return listPullRequestSubscriptionsForWebhook(
        subscriptionTarget,
        options,
        dependencies.github.integrationStorage,
      );
    });
  const retireSubscription =
    dependencies.retireSubscription ??
    ((id: string, status: 'open' | 'closed' | 'merged') => {
      if (!dependencies.github) throw new Error('GitHub integration is required to retire webhook subscriptions.');
      return retirePullRequestSubscription(id, status, dependencies.github.integrationStorage);
    });
  const subscriptions = await listSubscriptions(target, { includeTerminal: notification.action === 'reopened' });
  let delivered = 0;
  let failed = 0;
  let skipped = 0;

  for (const subscription of subscriptions) {

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Pass dependencies.github when constructing/calling dispatchGithubWebhook so integrationStorage is available
  2. Supply a custom dependencies.listSubscriptions override if running without the full GitHub integration
  3. Make dependencies.github a required constructor/parameter type so TypeScript catches the omission at compile time
  4. Add an upfront guard at the top of dispatchGithubWebhook that fails fast with a configuration error listing the missing dependency

Example fix

// before
await dispatchGithubWebhook(notification, { controller, sessions });
// after
await dispatchGithubWebhook(notification, {
  controller,
  sessions,
  github: { integrationStorage, sourceControlStorage },
});
Defensive patterns

Strategy: validation

Validate before calling

type WebhookDeps = { github?: GithubWebhookDispatchIntegration; listSubscriptions?: ... };
function assertGithubDeps(deps: WebhookDeps): asserts deps is WebhookDeps & { github: GithubWebhookDispatchIntegration } {
  if (!deps.github && !deps.listSubscriptions) {
    throw new Error('dispatchGithubWebhook requires dependencies.github or a listSubscriptions override.');
  }
}

Type guard

function canListSubscriptions(deps: { github?: unknown; listSubscriptions?: unknown }): boolean {
  return typeof deps.listSubscriptions === 'function' || typeof deps.github === 'object' && deps.github !== null;
}

Try / catch

try {
  await dispatchGithubWebhook(notification, deps);
} catch (err) {
  if ((err as Error).message.includes('required to load webhook subscriptions')) {
    logger.error('Webhook dispatcher misconfigured: pass dependencies.github');
    return { delivered: 0, failed: 0, skipped: 0 };
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling dispatchGithubWebhook without providing dependencies.github (or a custom dependencies.listSubscriptions) when a pull-request notification needs subscriptions listed.

Common situations: Wiring the webhook dispatcher in a new entry point (server route, queue consumer) and forgetting to pass the GitHub integration dependency; test harness constructs partial dependencies; a refactor made the github dependency optional in the type but required at runtime.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


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