mastra-ai/mastra · error

GithubIntegration source-control storage has not been initia

Error message

GithubIntegration source-control storage has not been initialized.

What it means

The sourceControlStorage getter resolves storage from an explicit #sourceControlStorage or falls back to #storage.sourceControl; it throws when neither is available. Source-control storage backs installations and repositories, so the integration cannot operate on GitHub repos until it is injected.

Source

Thrown at mastracode/factory/src/integrations/github/integration.ts:387

  /** Whether a GitHub login belongs to this integration's App. */
  isFactoryCommentAuthor(login: string | null | undefined): boolean {
    return typeof login === 'string' && login.toLowerCase() === `${this.#slug}[bot]`.toLowerCase();
  }

  /** Extra bot logins authorized to trigger author-gated PR notifications. */
  get authorizedBots(): readonly string[] {
    return this.#authorizedBots;
  }

  get genericStorage(): IntegrationContext['storage']['generic'] {
    if (!this.#storage) throw new Error('GithubIntegration storage has not been initialized.');
    return this.#storage.generic;
  }

  get sourceControlStorage(): IntegrationContext['storage']['sourceControl'] {
    const storage = this.#sourceControlStorage ?? this.#storage?.sourceControl;
    if (!storage) throw new Error('GithubIntegration source-control storage has not been initialized.');
    return storage;
  }

  get integrationStorage(): GithubSubscriptionStorage {
    if (!this.#storage) throw new Error('GithubIntegration storage has not been initialized.');
    return this.#storage.generic as unknown as GithubSubscriptionStorage;
  }

  /** Resolve a stored GitHub locator without scanning installations or repositories. */
  async #resolveIntakeDispatch({
    orgId,
    externalSource,
  }: {
    orgId: string;
    externalSource: { type: string; externalId: string };
  }): Promise<{ connection: IntegrationConnection; sourceId: string; issueId: string } | null> {
    const target = parseGithubExternalTarget(externalSource.externalId);
    if (!target) return null;

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Initialize the integration with a storage context that includes a sourceControl namespace before use
  2. Register the integration via the standard factory so storage injection happens automatically
  3. Confirm the storage implementation passed in exposes a sourceControl sub-namespace

Example fix

// before
const gh = new GithubIntegration(config);
await gh.sourceControlStorage.repositories.get({ orgId, id }); // throws
// after
const gh = new GithubIntegration(config);
await factory.initialize(gh, { storage }); // storage includes storage.sourceControl
await gh.sourceControlStorage.repositories.get({ orgId, id });
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const repo = await gh.sourceControlStorage.repositories.get({ orgId, id });
} catch (e) {
  if (e.message === 'GithubIntegration source-control storage has not been initialized.') {
    // ensure the integration was initialized with a storage context containing sourceControl
  } else throw e;
}

Prevention

When it happens

Trigger: Accessing integration.sourceControlStorage — or anything downstream of it such as repository/credential resolution — before the storage context has been injected into the integration.

Common situations: Using the integration outside the factory that wires IntegrationContext; calling repository APIs during app startup prior to storage wiring; a host app that registers the integration but never provides sourceControl storage bindings.

Related errors


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