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 postView on GitHub (pinned to 75dd419e61)
Solutions
- Set both `clientId` and `clientSecret` from your Linear OAuth application settings and pass them to the constructor.
- Check the message — it names exactly which keys are missing.
- Verify the env vars are present in the deploy environment (e.g. `printenv | grep LINEAR`) and loaded before bootstrap.
- 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
- Validate env vars at process startup before constructing integrations.
- Add both LINEAR_CLIENT_ID and LINEAR_CLIENT_SECRET to .env.example and deploy secrets.
- Prefer explicit throwing over `?? ''` defaults so misconfiguration is obvious.
- Check the error message — it lists exactly which keys were missing.
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
- Google client ID is required. Provide it in the options or s
- [mastra/auth-ee] ${featureList} ${configuredFeatures.length
- Clerk JWKS URI, secret key and publishable key are required,
- Redirect URI is required for SSO login
- [MastraAuthGoogle] GOOGLE_COOKIE_PASSWORD is required for Go
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/b702e6b88b853f23.
Report an issue: GitHub.