{"record":{"id":"5e1cbfb01e49f48a","repo":"mastra-ai/mastra","slug":"linear-capabilities-require-an-oauth-connection-5e1cbf","errorCode":null,"errorMessage":"Linear capabilities require an OAuth connection.","messagePattern":"Linear capabilities require an OAuth connection\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/factory/src/integrations/platform/linear/integration.ts","lineNumber":682,"sourceCode":"  if (!cursor) return {};\n  if (sourceIds.length === 1) return { [sourceIds[0]!]: cursor };\n  try {\n    const parsed = JSON.parse(cursor) as unknown;\n    if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) throw new Error();\n    return parsed as Record<string, string | null>;\n  } catch {\n    throw new Error('Linear cursor is invalid.');\n  }\n}\n\nfunction encodeCursor(state: Record<string, string | null>, sourceIds: string[]): string {\n  if (sourceIds.length === 1) return state[sourceIds[0]!]!;\n  return JSON.stringify(state);\n}\n\nfunction requireLinearConnection(connection: IntegrationConnection): void {\n  if (connection.type !== 'oauth') {\n    throw new Error('Linear capabilities require an OAuth connection.');\n  }\n}\n\nfunction isNotFound(error: unknown): boolean {\n  return error instanceof PlatformApiError && error.status === 404;\n}\n\nfunction optionalPositiveIntegerEnv(name: string): number | undefined {\n  const value = process.env[name]?.trim();\n  if (!value) return undefined;\n  const parsed = Number(value);\n  if (!Number.isSafeInteger(parsed) || parsed <= 0) {\n    throw new Error(`${name} must be a positive integer.`);\n  }\n  return parsed;\n}\n","sourceCodeStart":664,"sourceCodeEnd":699,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/factory/src/integrations/platform/linear/integration.ts#L664-L699","documentation":"Linear capabilities authenticate via OAuth only; `requireLinearConnection` is called before executing capability operations and throws when the supplied `IntegrationConnection` has a `type` other than 'oauth' (e.g. 'api-key', 'webhook', or none). The library refuses to proceed because non-OAuth credentials cannot provide the scopes Linear capabilities need.","triggerScenarios":"Invoking a Linear capability (project sync, issue operations) while passing a connection object created with `type: 'api-key'` or similar, or a connection resolved from a different integration's credential store.","commonSituations":"Teams that previously used a Linear API key integration switching to the platform integration without re-authorizing OAuth; reusing a shared connection object across integrations; connection record in storage migrated with the wrong type field.","solutions":["Complete the Linear OAuth flow and pass the resulting oauth connection to the capability call.","Check `connection.type === 'oauth'` before invoking capabilities and surface a re-auth prompt otherwise.","Ensure connection resolution looks up the Linear integration's connection, not another integration's.","If a stored connection has the wrong type, delete it and re-connect rather than editing the type field."],"exampleFix":"// before\nrunCapability({ connection: getStoredConnection('linear-api-key') });\n// after\nconst conn = getStoredConnection('linear');\nif (conn.type !== 'oauth') throw new Error('Re-authorize Linear via OAuth');\nrunCapability({ connection: conn });","handlingStrategy":"validation","validationCode":"function ensureLinearOauth(connection: IntegrationConnection): void {\n  if (connection.type !== 'oauth') {\n    throw new Error(`Linear requires an OAuth connection (got: ${connection.type}). Re-authorize Linear.`);\n  }\n}","typeGuard":"function isOauthConnection(c: IntegrationConnection): c is IntegrationConnection & { type: 'oauth' } {\n  return c.type === 'oauth';\n}","tryCatchPattern":"try {\n  await runLinearCapability({ connection });\n} catch (err) {\n  if (err instanceof Error && err.message === 'Linear capabilities require an OAuth connection.') {\n    return promptReauthorization('linear');\n  }\n  throw err;\n}","preventionTips":["Check connection.type before building capability menus so OAuth-only integrations are never offered with key credentials.","Scope connection lookups per integration id to avoid cross-integration credential reuse.","Re-create stored connections via the OAuth flow instead of mutating the type field after migration."],"tags":["linear","oauth","authentication","configuration"],"backgroundTag":"oauth-connection-required","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}