supabase/supabase · warning

Method ${method} Not Allowed

Error message

Method ${method} Not Allowed

What it means

Single-snippet endpoint keyed by [id]. Implements GET only (loads the snippet with its SQL content via getSnippet). Allow header lists GET. Other verbs return 405. Mutations live on /content (PUT/DELETE), not here.

Source

Thrown at apps/studio/pages/api/platform/projects/[ref]/content/item/[id].ts:16

import { NextApiRequest, NextApiResponse } from 'next'

import { apiWrapper } from '@/lib/api/apiWrapper'
import { getSnippet } from '@/lib/api/snippets.utils'

const wrappedHandler = (req: NextApiRequest, res: NextApiResponse) => apiWrapper(req, res, handler)

async function handler(req: NextApiRequest, res: NextApiResponse) {
  const { method } = req

  switch (method) {
    case 'GET':
      return handleGetAll(req, res)
    default:
      res.setHeader('Allow', ['GET'])
      res.status(405).json({ data: null, error: { message: `Method ${method} Not Allowed` } })
  }
}

const handleGetAll = async (req: NextApiRequest, res: NextApiResponse) => {
  try {
    const snippet = await getSnippet(req.query.id as string)

    return res.status(200).json(snippet)
  } catch (error) {
    if (error instanceof Error && error.message.includes('not found')) {
      return res.status(404).json({ message: 'Content not found.' })
    }
    return res.status(500).json({ data: null, error: { message: 'Internal Server Error' } })
  }
}

export default wrappedHandler

View on GitHub (pinned to beee91b9c2)

Solutions

  1. Use GET on /content/item/[id] to load a snippet's full body.
  2. Use PUT/DELETE on /content (collection) for mutations.
  3. Treat the item route as read-only.

Example fix

// before
await fetch(`${base}/content/item/${id}`, { method: 'DELETE' }) // 405
// after
await fetch(`${base}/content?ids=${id}`, { method: 'DELETE' })
Defensive patterns

Strategy: validation

Validate before calling

function assertGetOnly(method: string) {
  if (method.toUpperCase() !== 'GET') throw new Error('content/item/[id] is GET-only')
}

Try / catch

if (res.status === 405) {
  throw new Error('Mutate via /content (PUT/DELETE), not /content/item/[id].')
}

Prevention

When it happens

Trigger: PUT, POST, PATCH, or DELETE to /api/platform/projects/[ref]/content/item/[id].

Common situations: A client trying to delete a snippet via its item URL; or PUT-updating through the item route.

Related errors


AI-assisted analysis of supabase/supabase@beee91b9c2 (2026-08-12). Data as JSON: /api/errors/360257331dcb49aa. Report an issue: GitHub.