mastra-ai/mastra · error

LinearIntegration is missing required config: ${missing.join

Error message

LinearIntegration is missing required config: ${missing.join(', ')}.

What it means

The `LinearIntegration` constructor validates its config synchronously and throws when any of the required keys `clientId` or `clientSecret` is missing or falsy, listing the missing keys. These credentials come from your Linear OAuth application and are needed to build authorize URLs and exchange/refresh tokens.

Source

Thrown at mastracode/factory/src/integrations/linear/integration.ts:580

    if (externalSource.type !== 'issue') return null;
    const connection = await this.loadConnection(orgId);
    if (!connection) return null;
    const accessToken = await this.getFreshAccessToken(connection);
    return { connection: { type: 'oauth', accessToken }, issueId: externalSource.externalId };
  }
  /**
   * The OAuth connect/callback flow round-trips a signed `state` through
   * Linear, so a multi-replica deploy needs a deployment-stable state secret.
   */
  readonly requiresStableStateSigner = true;

  readonly #clientId: string;
  readonly #clientSecret: string;

  constructor(config: LinearIntegrationConfig) {
    const missing = (['clientId', 'clientSecret'] as const).filter(key => !config[key]);
    if (missing.length > 0) {
      throw new Error(`LinearIntegration is missing required config: ${missing.join(', ')}.`);
    }
    this.#clientId = config.clientId;
    this.#clientSecret = config.clientSecret;
  }

  // ── OAuth ────────────────────────────────────────────────────────────────

  /**
   * Build the OAuth authorize URL. `prompt=consent` forces the workspace
   * picker even for an already-authorized user, so "reconnect" can switch
   * workspaces.
   */
  buildAuthorizeUrl(state: string, redirectUri: string): string {
    const url = new URL(LINEAR_AUTHORIZE_URL);
    url.searchParams.set('client_id', this.#clientId);
    url.searchParams.set('redirect_uri', redirectUri);
    url.searchParams.set('response_type', 'code');
    // `comments:create` lets the agent's linear_create_comment tool post

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Set both `clientId` and `clientSecret` from your Linear OAuth application settings and pass them to the constructor.
  2. Check the message — it names exactly which keys are missing.
  3. Verify the env vars are present in the deploy environment (e.g. `printenv | grep LINEAR`) and loaded before bootstrap.
  4. Fail fast at startup: constructing the integration throws immediately, so let the process crash with this message rather than deferring.

Example fix

// before (env may be undefined)
new LinearIntegration({ clientId: process.env.LINEAR_CLIENT_ID ?? '', clientSecret: process.env.LINEAR_CLIENT_SECRET ?? '' });
// after
const clientId = process.env.LINEAR_CLIENT_ID;
const clientSecret = process.env.LINEAR_CLIENT_SECRET;
if (!clientId || !clientSecret) throw new Error('Set LINEAR_CLIENT_ID and LINEAR_CLIENT_SECRET');
new LinearIntegration({ clientId, clientSecret });
Defensive patterns

Strategy: validation

Validate before calling

const clientId = process.env.LINEAR_CLIENT_ID;
const clientSecret = process.env.LINEAR_CLIENT_SECRET;
if (!clientId) throw new Error('LINEAR_CLIENT_ID is required');
if (!clientSecret) throw new Error('LINEAR_CLIENT_SECRET is required');
const integration = new LinearIntegration({ clientId, clientSecret });

Type guard

function hasLinearConfig(c: unknown): c is { clientId: string; clientSecret: string } {
  const o = c as Record<string, unknown>;
  return typeof o.clientId === 'string' && o.clientId.length > 0 && typeof o.clientSecret === 'string' && o.clientSecret.length > 0;
}

Prevention

When it happens

Trigger: Calling `new LinearIntegration({ clientId: '', clientSecret })` (or vice versa) — typically because environment variables (e.g. LINEAR_CLIENT_ID / LINEAR_CLIENT_SECRET) are unset or empty at bootstrap, so `process.env.X ?? ''` yields an empty string.

Common situations: Missing `.env` entries in local dev; deploy environments where the secrets were never configured; typos in env var names; conditional config objects built with spread where the key ends up undefined; reading from a config loader that drops empty strings.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


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