mastra-ai/mastra · error
GitHub pull requests require an owner/repository source.
Error message
GitHub pull requests require an owner/repository source.
What it means
#repositoryClient parses the sourceId into { owner, repo } via splitRepoFullName and throws when parsing fails, because GitHub pull-request operations require a well-formed owner/repository full name to build the Octokit request.
Source
Thrown at mastracode/factory/src/integrations/github/integration.ts:712
const octokit = this.getInstallationOctokit(installationId);
try {
const { data } = await octokit.issues.createComment({
owner: parts.owner,
repo: parts.repo,
issue_number: issueNumber,
body: input.body,
});
return { id: String(data.id), url: data.html_url };
} catch (err) {
if (isNotFoundError(err)) return null;
throw err;
}
}
#repositoryClient(connection: IntegrationConnection, sourceId: string) {
const installationId = getGithubInstallationId(connection);
const parts = splitRepoFullName(sourceId);
if (!parts) throw new Error('GitHub pull requests require an owner/repository source.');
return { octokit: this.getInstallationOctokit(installationId), parts };
}
async #listPullRequests(input: InputOf<'listPullRequests'>) {
const { octokit, parts } = this.#repositoryClient(input.connection, input.sourceId);
const page = parsePositiveCursor(input.cursor);
const response = await octokit.pulls.list({
...parts,
state: input.state ?? 'open',
per_page: LIST_PAGE_SIZE,
page,
});
const pullRequests = response.data
.filter(pr => input.includeDrafts !== false || !pr.draft)
.map(pr => parsePullRequest(pr));
return {
pullRequests,
nextCursor: response.data.length === LIST_PAGE_SIZE ? String(page + 1) : null,View on GitHub (pinned to 75dd419e61)
Solutions
- Pass sourceId as the GitHub full name 'owner/repo'
- Normalize stored source identifiers to owner/repo when creating connections
- Use splitRepoFullName (or an equivalent check) on input before calling the integration to give a better upstream error
- Update stale connections after repository transfers/renames
Example fix
// before
await gh.listPullRequests({ connection, sourceId: 'my-repo' });
// after
await gh.listPullRequests({ connection, sourceId: 'acme/my-repo' }); Defensive patterns
Strategy: validation
Validate before calling
const parts = sourceId.split('/');
if (parts.length !== 2 || !parts[0] || !parts[1]) {
throw new Error(`sourceId must be 'owner/repo', got: ${sourceId}`);
} Type guard
function isRepoFullName(s: string): s is `${string}/${string}` {
const [owner, repo, ...rest] = s.split('/');
return rest.length === 0 && Boolean(owner && repo);
} Try / catch
try {
await gh.listPullRequests({ connection, sourceId });
} catch (e) {
if (e.message === 'GitHub pull requests require an owner/repository source.') {
// fix the stored source identifier for this connection
} else throw e;
} Prevention
- Store GitHub sources canonically as 'owner/repo' at connection creation time
- Normalize or reject URLs/ids before saving sourceId
- Re-validate stored sourceIds after repository renames or transfers
When it happens
Trigger: Calling listPullRequests (or any PR operation routed through #repositoryClient) with a sourceId that is not in 'owner/repo' format — e.g. a bare repo name, a URL, a numeric repo id, or an empty string.
Common situations: Passing a database record id instead of the GitHub full name; users typing 'my-repo' without the owner; storing a clone URL in sourceId; renaming a repository and keeping a stale slug.
Related errors
- A review comment requires commitId, path, line, and side unl
- A multi-line review comment requires both startLine and star
- GitHub triage comments require an owner/repository source.
- GitHub ${resource} id must be a positive integer.
- ${message}
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/e7f1bc2d10b1e398.
Report an issue: GitHub.