{"record":{"id":"62c27b539a1aaece","repo":"mastra-ai/mastra","slug":"not-logged-in-run-mastra-auth-login-interactive","errorCode":null,"errorMessage":"Not logged in. Run `mastra auth login` interactively or set MASTRA_API_TOKEN.","messagePattern":"Not logged in\\. Run `mastra auth login` interactively or set MASTRA_API_TOKEN\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/auth/credentials.ts","lineNumber":346,"sourceCode":"  return creds;\n}\n\nfunction isInteractive(): boolean {\n  return Boolean(process.stdin.isTTY && process.stdout.isTTY) && !process.env.CI;\n}\n\nexport async function getToken(signal?: AbortSignal, options: LoginOptions = {}): Promise<string> {\n  signal?.throwIfAborted();\n\n  // CI/CD headless path\n  const envToken = process.env.MASTRA_API_TOKEN;\n  if (envToken) return envToken;\n\n  const creds = await loadCredentials();\n  signal?.throwIfAborted();\n  if (!creds) {\n    if (options.allowLogin === false || !isInteractive()) {\n      throw new Error('Not logged in. Run `mastra auth login` interactively or set MASTRA_API_TOKEN.');\n    }\n    const newCreds = await login(signal, options);\n    return newCreds.token;\n  }\n\n  // Try a quick verify to see if the token is still valid.\n  if (await verifyToken(creds.token, signal)) return creds.token;\n  signal?.throwIfAborted();\n\n  // Token might be expired — attempt refresh\n  const refreshed = await tryRefreshToken(creds, signal);\n  if (refreshed) return refreshed;\n  signal?.throwIfAborted();\n\n  if (options.allowLogin === false || !isInteractive()) {\n    throw new Error('Session expired. Run `mastra auth login` interactively or set MASTRA_API_TOKEN.');\n  }\n  const newCreds = await login(signal, options);","sourceCodeStart":328,"sourceCodeEnd":364,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/cli/src/commands/auth/credentials.ts#L328-L364","documentation":"getToken resolves the bearer token for platform commands: it checks MASTRA_API_TOKEN, then stored credentials. If neither exists and interactive login is disallowed (options.allowLogin === false or the process is not interactive, e.g. CI/non-TTY), it throws this error instead of launching the browser login flow, since login cannot be prompted in a non-interactive context.","triggerScenarios":"A command calls getToken with no MASTRA_API_TOKEN set and no credentials file, while options.allowLogin is false or isInteractive() is false (piped output, CI runner, non-TTY shell).","commonSituations":"CI pipelines missing the MASTRA_API_TOKEN secret; running the CLI from a script or Docker container without a TTY; fresh environments without `mastra auth login`; env var typo'd (MASTRA_API_KEY instead of MASTRA_API_TOKEN).","solutions":["Set MASTRA_API_TOKEN with a valid platform token in the environment/CI secrets.","Run `mastra auth login` once in an interactive terminal so stored credentials exist.","Run the command in a TTY (drop output piping) so interactive login can trigger.","Check the env var is spelled MASTRA_API_TOKEN and is exported in the current shell."],"exampleFix":"// before (CI)\n- run: mastra deploy\n// after\n- run: mastra deploy\n  env:\n    MASTRA_API_TOKEN: ${{ secrets.MASTRA_API_TOKEN }}","handlingStrategy":"validation","validationCode":"if (!process.env.MASTRA_API_TOKEN && !isTTY()) {\n  throw new Error('Set MASTRA_API_TOKEN for non-interactive use, or run `mastra auth login` in a terminal');\n}","typeGuard":null,"tryCatchPattern":"try {\n  const token = await getToken(signal, { allowLogin: false });\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('Not logged in')) {\n    console.error('Provide MASTRA_API_TOKEN or authenticate interactively first.');\n    process.exitCode = 1;\n    return;\n  }\n  throw err;\n}","preventionTips":["Export MASTRA_API_TOKEN in CI secrets and non-TTY scripts.","Authenticate once interactively before running the CLI in automation.","Check the exact env var name MASTRA_API_TOKEN (not API_KEY) and that it is exported.","Use `allowLogin: false` deliberately in scripts so failures surface early with a clear message."],"tags":["cli","auth","non-interactive","ci","env-var"],"backgroundTag":"missing-env-var","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}