nextauthjs/next-auth · error · UnknownAction

Only GET and POST requests are supported

Error message

Only GET and POST requests are supported

What it means

toInternalRequest converts the framework's Request into an internal request and only supports GET and POST methods. Any other HTTP method (PUT, DELETE, PATCH, HEAD with body semantics, OPTIONS) is rejected with UnknownAction before routing.

Source

Thrown at packages/core/src/lib/utils/web.ts:33

async function getBody(req: Request): Promise<Record<string, any> | undefined> {
  if (!("body" in req) || !req.body || req.method !== "POST") return

  const contentType = req.headers.get("content-type")
  if (contentType?.includes("application/json")) {
    return await req.json()
  } else if (contentType?.includes("application/x-www-form-urlencoded")) {
    const params = new URLSearchParams(await req.text())
    return Object.fromEntries(params)
  }
}

export async function toInternalRequest(
  req: Request,
  config: AuthConfig
): Promise<RequestInternal | undefined> {
  try {
    if (req.method !== "GET" && req.method !== "POST")
      throw new UnknownAction("Only GET and POST requests are supported")

    // Defaults are usually set in the `init` function, but this is needed below
    config.basePath ??= "/auth"

    const url = new URL(req.url)

    const { action, providerId } = parseActionAndProviderId(
      url.pathname,
      config.basePath
    )

    return {
      url,
      action,
      providerId,
      method: req.method,
      headers: Object.fromEntries(req.headers),
      body: req.body ? await getBody(req) : undefined,

View on GitHub (pinned to a1a16a5a77)

Solutions

  1. Use only GET (e.g. session, csrf, providers) and POST (signin, signout, callback) requests against auth routes
  2. Sign out with POST /auth/signout rather than DELETE /auth/session
  3. Configure the server/CORS layer to handle OPTIONS preflights before they reach the auth handler

Example fix

// before
await fetch("/api/auth/session", { method: "DELETE" }) // sign out
// after
await fetch("/api/auth/signout", { method: "POST" })
Defensive patterns

Strategy: try-catch

Validate before calling

if (!["GET","POST"].includes(request.method)) return new Response("Method Not Allowed", { status: 405 });

Type guard

function isSupportedMethod(m: string): m is "GET"|"POST" { return m === "GET" || m === "POST"; }

Try / catch

try { return await auth(req) } catch (e) { if (String(e.message).includes("Only GET and POST")) return new Response("Method Not Allowed", { status: 405 }); throw e; }

Prevention

When it happens

Trigger: Sending DELETE /auth/session, PUT to a signin/callback route, or an OPTIONS preflight hitting the auth handler directly without being short-circuited by the server.

Common situations: REST clients calling the session endpoint with DELETE expecting it to sign out (use POST /auth/signout instead); misconfigured CORS middleware letting OPTIONS reach the auth route; frameworks wiring auth to methods other than GET/POST.

Related errors


AI-assisted analysis of nextauthjs/next-auth@a1a16a5a77 (2026-08-28). Data as JSON: /api/errors/853ca532944bf0c1. Report an issue: GitHub.