nextauthjs/next-auth · error · TypeError

Missing Postmark API Key

Error message

Missing Postmark API Key

What it means

The Postmark provider throws a TypeError when provider.apiKey is falsy before calling Postmark's API, since the X-Postmark-Server-Token header is mandatory. Like other provider guards, this fails fast as a configuration error instead of producing an obscure 401 from the API. No network request is made when this fires.

Source

Thrown at packages/core/src/providers/postmark.ts:15

import type { EmailConfig, EmailUserConfig } from "./index.js"
import { html, text } from "../lib/utils/email.js"

/** @todo Document this */
export default function Postmark(config: EmailUserConfig): EmailConfig {
  return {
    id: "postmark",
    type: "email",
    name: "Postmark",
    from: "Auth.js <no-reply@authjs.dev>",
    maxAge: 24 * 60 * 60,
    async sendVerificationRequest(params) {
      const { identifier: to, provider, url, theme } = params
      const { host } = new URL(url)
      if (!provider.apiKey) throw new TypeError("Missing Postmark API Key")
      const res = await fetch("https://api.postmarkapp.com/email", {
        method: "POST",
        headers: {
          Accept: "application/json",
          "Content-Type": "application/json",
          "X-Postmark-Server-Token": provider.apiKey,
        },
        body: JSON.stringify({
          From: provider.from,
          To: to,
          Subject: `Sign in to ${host}`,
          TextBody: text({ url, host }),
          HtmlBody: html({ url, host, theme }),
          MessageStream: "outbound",
        }),
      })

      if (!res.ok)

View on GitHub (pinned to a1a16a5a77)

Solutions

  1. Set apiKey: process.env.POSTMARK_API_KEY and ensure the env var exists in all environments
  2. Confirm the value is a Postmark *Server* token (starts with a UUID-like string), not an account-level token
  3. Restart/redeploy after adding the env var so the process picks it up
  4. Add a startup check that required email env vars are present before serving traffic

Example fix

// before
Postmark({ from: "no-reply@example.com" }) // apiKey missing -> TypeError
// after
Postmark({
  apiKey: process.env.POSTMARK_API_KEY,
  from: "no-reply@example.com",
})
Defensive patterns

Strategy: validation

Validate before calling

if (!process.env.POSTMARK_API_KEY) throw new Error('POSTMARK_API_KEY is required')
if (!/^[0-9a-f-]{36}$/.test(process.env.POSTMARK_API_KEY)) console.warn('POSTMARK_API_KEY does not look like a Postmark server token')

Type guard

function isPostmarkConfigured(p: { apiKey?: string }): p is { apiKey: string } {
  return typeof p.apiKey === 'string' && p.apiKey.length > 0
}

Try / catch

try {
  await sendVerificationRequest(params)
} catch (e) {
  if (e instanceof TypeError && e.message === 'Missing Postmark API Key') {
    console.error('Postmark provider misconfigured: set apiKey (server token) via POSTMARK_API_KEY')
  }
}

Prevention

When it happens

Trigger: sendVerificationRequest runs with a Postmark provider config where apiKey is undefined/null/empty — e.g. process.env.POSTMARK_API_KEY unset in the deployment environment or the option key misspelled — hitting `if (!provider.apiKey)` immediately.

Common situations: Deploying to an environment where POSTMARK_API_KEY was never set (works locally via .env, fails in prod); rotating the Postmark server token and forgetting to update the env var; passing the token under the wrong config key.

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 nextauthjs/next-auth@a1a16a5a77 (2026-08-28). Data as JSON: /api/errors/b867cae32d62004b. Report an issue: GitHub.