{"record":{"id":"98456b1f0c9398fa","repo":"mastra-ai/mastra","slug":"github-triage-comments-require-an-owner-repository","errorCode":null,"errorMessage":"GitHub triage comments require an owner/repository source.","messagePattern":"GitHub triage comments require an owner/repository source\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/factory/src/integrations/github/integration.ts","lineNumber":1278,"sourceCode":"        labels: (issue.labels ?? [])\n          .map(label => (typeof label === 'string' ? label : label.name))\n          .filter((name): name is string => Boolean(name)),\n        ...(issue.user?.login ? { author: issue.user.login } : {}),\n        createdAt: issue.created_at,\n        updatedAt: issue.updated_at,\n      };\n    } catch {\n      return undefined;\n    }\n  }\n\n  /**\n   * Session-scoped agent tools for token refresh and PR subscriptions in\n   * sessions bound to a GitHub-backed project. Empty elsewhere.\n   */\n  async upsertFactoryTriageComment(input: GithubTriageCommentUpsertInput): Promise<GithubTriageCommentUpsertResult> {\n    const parts = splitRepoFullName(input.repository);\n    if (!parts) throw new Error('GitHub triage comments require an owner/repository source.');\n    const octokit = this.getInstallationOctokit(input.installationId);\n    const comments = [] as Array<{\n      id: number;\n      body?: string | null;\n      user?: { login?: string } | null;\n      html_url: string;\n    }>;\n    for (let page = 1; ; page += 1) {\n      const response = await octokit.issues.listComments({\n        ...parts,\n        issue_number: input.issueNumber,\n        per_page: 100,\n        page,\n      });\n      comments.push(...response.data);\n      if (response.data.length < 100) break;\n    }\n    const existing = comments","sourceCodeStart":1260,"sourceCodeEnd":1296,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/factory/src/integrations/github/integration.ts#L1260-L1296","documentation":"upsertFactoryTriageComment requires input.repository to be a full 'owner/repo' identifier that splitRepoFullName can parse. When the repository string is empty, malformed, or not owner/repo shaped, the method refuses to proceed because it cannot address the GitHub REST API.","triggerScenarios":"Calling upsertFactoryTriageComment with input.repository = '' , 'my-repo' (no owner), 'owner/repo/extra', or a URL instead of the owner/repo slug.","commonSituations":"Project source configured with only a repo name; parsing a git remote URL into the wrong variable; pulling repository name from a webhook payload field that uses a full name vs slug inconsistently.","solutions":["Pass the full owner/repo slug, e.g. 'acme/widgets'.","Derive the slug from the git remote URL by stripping the host and '.git'.","Validate the repository string with a /^[^/]+\\/[^/]+$/ check before calling.","Check where the repository value is populated in your project/config wiring for truncation."],"exampleFix":"// before\nawait gh.upsertFactoryTriageComment({ repository: 'widgets', ... });\n// after\nawait gh.upsertFactoryTriageComment({ repository: 'acme/widgets', ... });","handlingStrategy":"validation","validationCode":"const GITHUB_SLUG_RE = /^[^/]+\\/[^/]+$/;\nif (!GITHUB_SLUG_RE.test(input.repository)) throw new Error(`repository must be owner/repo, got: ${input.repository}`);","typeGuard":"function isRepoSlug(v: unknown): v is string {\n  return typeof v === 'string' && /^[^/]+\\/[^/]+$/.test(v);\n}","tryCatchPattern":"try {\n  await gh.upsertFactoryTriageComment({ repository: repo, ...input });\n} catch (e) {\n  if ((e as Error).message.includes('owner/repository')) throw new Error(`Invalid repository slug: ${repo}`);\n  throw e;\n}","preventionTips":["Store the full owner/repo slug in project config, never just the repo name.","Normalize git remote URLs to owner/repo at ingestion time.","Unit-test repo slug parsing with malformed inputs."],"tags":["github","validation","input"],"backgroundTag":"invalid-repository-slug","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}