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
- Pass dependencies.github when constructing/calling dispatchGithubWebhook so integrationStorage is available
- Supply a custom dependencies.listSubscriptions override if running without the full GitHub integration
- Make dependencies.github a required constructor/parameter type so TypeScript catches the omission at compile time
- 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
- Make dependencies.github a required field in the dispatcher's dependency type
- Add a startup check in the server bootstrap that the GitHub integration is wired into the webhook dispatcher
- Cover the webhook entry point with a smoke test that delivers a synthetic PR notification
- Keep a single factory function for building webhook dependencies so call sites can't drift
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
- GitHub integration is required to retire webhook subscriptio
- GitHub subscription ${subscription.id} is missing its sessio
- GitHub subscription ${subscription.id} has no Factory sessio
- Session ${sessionId} did not bind thread ${threadId}.
- WorkOS webhook secret is required. Provide it in options or
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/e96686e1822c062f.
Report an issue: GitHub.