mastra-ai/mastra · error

GitHub capabilities require an owner/repository source.

Error message

GitHub capabilities require an owner/repository source.

What it means

Thrown by splitRepository when a sourceId does not contain an owner/repo pair separated by a slash (no slash, leading slash, or trailing slash). GitHub REST paths are built from owner and repo, so any capability call with a malformed source id fails here before a request is made.

Source

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

}

function repositoryPath(sourceId: string, suffix: string): string {
  const { owner, repo } = splitRepository(sourceId);
  return `${API_PREFIX}/github/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/${suffix}`;
}

function pullRequestPath(
  input: { connection: IntegrationConnection; sourceId: string },
  pullRequestId: string,
): string {
  requireGithubConnection(input.connection);
  return repositoryPath(input.sourceId, `pulls/${requirePositiveId(pullRequestId, 'pull request')}`);
}

function splitRepository(sourceId: string): { owner: string; repo: string } {
  const slash = sourceId.indexOf('/');
  if (slash <= 0 || slash === sourceId.length - 1) {
    throw new Error('GitHub capabilities require an owner/repository source.');
  }
  return { owner: sourceId.slice(0, slash), repo: sourceId.slice(slash + 1) };
}

function parseIntakeIssue(sourceId: string, issue: GithubIssue): IntakeIssue {
  return {
    id: String(issue.number),
    identifier: `#${issue.number}`,
    title: issue.title,
    url: issue.htmlUrl,
    author: issue.user?.login ?? null,
    state: issue.state,
    stateType: issue.state,
    priority: null,
    assignee: issue.assignees[0] ?? null,
    assignees: issue.assignees,
    source: sourceId,
    labels: issue.labels,

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Pass the full GitHub slug ('owner/repo') as sourceId
  2. Fix upstream source records so the stored slug matches GitHub's full_name
  3. Trim the value and re-check for stray leading/trailing slashes before calling
  4. Validate with a regex like /^[^/]+\/[^/]+$/ before invoking

Example fix

// before
await github.listPullRequests({ installationId, sourceIds: ['my-repo'] });
// after
await github.listPullRequests({ installationId, sourceIds: ['acme/my-repo'] });
Defensive patterns

Strategy: validation

Validate before calling

function isValidOwnerRepo(sourceId: string): boolean {
  const slash = sourceId.indexOf('/');
  return slash > 0 && slash < sourceId.length - 1;
}
if (!isValidOwnerRepo(sourceId)) throw new Error(`sourceId '${sourceId}' must be 'owner/repo'`);

Type guard

function isGithubSlug(s: string): s is `${string}/${string}` {
  const i = s.indexOf('/');
  return i > 0 && i < s.length - 1;
}

Try / catch

try {
  await github.listPullRequests({ installationId, sourceIds: [sourceId] });
} catch (err) {
  if (err instanceof Error && err.message.includes('owner/repository source')) {
    sourceId = await resolveGithubSlug(sourceId); // map local id -> owner/repo
  } else throw err;
}

Prevention

When it happens

Trigger: Calling any GitHub capability (issues, pulls, comments, etc.) with a sourceIds[0] value like 'my-repo', '/my-repo', or 'owner/' — anything where sourceId.indexOf('/') is <= 0 or at the last character.

Common situations: Passing a repository name instead of its full slug; the platform storing a local repo id instead of the GitHub full_name; trailing whitespace or trailing slash from copy-paste; intake sync wrote a slugless source.

Related errors


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