{"record":{"id":"d68cabb336a05f48","repo":"mastra-ai/mastra","slug":"failed-to-load-pull-request-subscriptions-respo","errorCode":null,"errorMessage":"Failed to load pull request subscriptions (${response.status}).","messagePattern":"Failed to load pull request subscriptions \\((.+?)\\)\\.","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/factory-ui/src/ui/domains/factory/services/githubSubscriptions.ts","lineNumber":47,"sourceCode":"    typeof value.repoFullName === 'string' &&\n    typeof value.pullRequestNumber === 'number' &&\n    Number.isInteger(value.pullRequestNumber) &&\n    value.pullRequestNumber > 0 &&\n    isPullRequestStatus(value.status) &&\n    typeof value.url === 'string'\n  );\n}\n\nexport async function listPullRequestSubscriptions(\n  baseUrl: string,\n  resourceId: string,\n  threadId: string,\n  projectPath?: string,\n): Promise<PullRequestSubscription[]> {\n  const params = new URLSearchParams({ resourceId, threadId });\n  if (projectPath) params.set('scope', projectPath);\n  const response = await fetch(`${baseUrl}/web/github/subscriptions?${params}`, { credentials: 'include' });\n  if (!response.ok) throw new Error(`Failed to load pull request subscriptions (${response.status}).`);\n\n  const body: unknown = await response.json();\n  if (!isRecord(body) || !Array.isArray(body.subscriptions)) {\n    throw new Error('Pull request subscriptions returned an invalid response.');\n  }\n  // one bad row must not hide every other pull request; warn so a widened server enum is not silent\n  const subscriptions = body.subscriptions.filter(isPullRequestSubscription);\n  const dropped = body.subscriptions.length - subscriptions.length;\n  if (dropped > 0 && import.meta.env.DEV) {\n    console.warn(`Dropped ${dropped} pull request subscription(s) the client does not understand.`);\n  }\n  return subscriptions;\n}\n","sourceCodeStart":29,"sourceCodeEnd":61,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/factory-ui/src/ui/domains/factory/services/githubSubscriptions.ts#L29-L61","documentation":"listPullRequestSubscriptions fetches GET /web/github/subscriptions and throws immediately if the HTTP response is not ok, with a message embedding the status code. Unlike the generic request helpers, it does not attempt to read a server error message; the failure is reported purely as 'Failed to load pull request subscriptions (<status>).'.","triggerScenarios":"Any non-OK response from GET {baseUrl}/web/github/subscriptions?resourceId=...&threadId=...[&scope=projectPath] with credentials: 'include' — e.g. 401 when the session cookie is missing/expired, 403 when projectPath scope is not permitted, 404 if the web route is absent, or 5xx server error.","commonSituations":"User session expired so credentials: 'include' carries no valid cookie, passing a projectPath the server does not recognize as a scope, calling before the GitHub web routes are mounted in a dev/proxy misconfiguration, or backend outage.","solutions":["Check the numeric status in the message and inspect the failing request in the network tab","Re-authenticate so a valid session cookie is sent with credentials: 'include'","Verify baseUrl points at the server exposing /web/github/subscriptions and that resourceId/threadId are non-empty","If scope (projectPath) was passed, confirm it matches a project the server knows; try omitting it"],"exampleFix":"// before\nconst subs = await listPullRequestSubscriptions(baseUrl, resourceId, threadId, staleProjectPath);\n// after\nif (!resourceId || !threadId) throw new Error('resourceId and threadId are required');\nconst subs = await listPullRequestSubscriptions(baseUrl, resourceId, threadId);","handlingStrategy":"retry","validationCode":"if (!isNonEmptyString(resourceId) || !isNonEmptyString(threadId)) throw new Error('resourceId and threadId are required for subscriptions');\nif (!baseUrl.startsWith('http')) throw new Error('Invalid baseUrl');","typeGuard":"function isPullRequestSubscription(v: unknown): v is PullRequestSubscription {\n  return typeof v === 'object' && v !== null && 'id' in v && typeof (v as { id: unknown }).id === 'string';\n}","tryCatchPattern":"async function loadSubscriptions(): Promise<PullRequestSubscription[]> {\n  try {\n    return await listPullRequestSubscriptions(baseUrl, resourceId, threadId, projectPath);\n  } catch (err) {\n    const msg = err instanceof Error ? err.message : String(err);\n    if (/401/.test(msg)) { await reauth(); return loadSubscriptions(); }\n    if (/5\\d\\d|Failed to load/.test(msg)) { await delay(1000); return loadSubscriptions(); }\n    throw err;\n  }\n}","preventionTips":["Ensure session cookies are fresh before calling authenticated /web routes","Omit the scope param when projectPath is not a confirmed server-known scope","Confirm the server version mounts /web/github/subscriptions","Use exponential backoff for transient 5xx failures"],"tags":["http","api","github-subscriptions"],"backgroundTag":"http-request-failed-with-status","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}