nuxt / nuxt/content

Invalid query validation should return 400 Bad Request instead of 500 Server Error

Open Beginner friendly
#3,813 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
TypeScript
Stars
3.7k
Forks
746
Avg merge
1d 16h
Merged PRs (30d)
3

Description

Is your feature request related to a problem? Please describe

When an invalid SQL query is sent to the query API endpoint(POST /__nuxt_content/[collection]/query), the assertSafeQuery() function throws an error that is not properly caught. This results in an HTTP 500 Server Error being returned to the client, when it should return HTTP 400 Bad Request instead.
Query validation errors (client-side mistakes) should be treated as client errors (4xx) rather than server errors (5xx).

This is causing critical issues for production applications:

  • Our application servers have monitoring systems that detect HTTP 5xx responses and trigger critical alerts. Invalid query validation errors are being incorrectly classified as server errors, causing our alert systems to fire even though there is no actual server problem.
  • According to standard HTTP status code conventions and REST API best practices, validation errors on client input should return 400 Bad Request, not 500 Server Error. Returning 500 violates these conventions and makes it difficult for client applications to properly handle and differentiate between validation errors and actual server failures.
Describe the solution you’d like

The error is thrown in src/runtime/api/query.post.ts, where assertSafeQuery() is called without error handling:

export default eventHandler(async (event) => {
  const { sql } = await readBody(event)
  const collection = getRouterParam(event, ‘collection’)! || event.path?.split(‘/’)?.[2] || ‘’

  assertSafeQuery(sql, collection)  // ← Unhandled error becomes 500

  const conf = useRuntimeConfig().content as RuntimeConfig[‘content’]
  if (conf.integrityCheck) {
    await checkAndImportDatabaseIntegrity(event, collection, conf)
  }

  return loadDatabaseAdapter(conf).all(sql)
})

Wrap the assertSafeQuery() call in a try-catch block and return a proper 400 error response:

  try {
    assertSafeQuery(sql, collection)
  } catch (error) {
    throw createError({
      statusCode: 400,
      statusMessage: ‘Bad Request’,
      data: {
        message: error instanceof Error ? error.message : ‘Invalid query’
      }
    })
  }
Describe alternatives you’ve considered

assertSafeQuery() itself may throw error with statusCode: 400 rather than wrapping the function.

Additional context
  • File affected: src/runtime/api/query.post.ts
  • Function: assertSafeQuery() in src/runtime/internal/security.ts

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/runtime/api/query.post.ts and trace assertSafeQuery() in src/runtime/internal/security.ts. Verify that invalid SQL sent to POST /__nuxt_content/[collection]/query produces a 400 Bad Request with the validation message, while valid queries retain their existing behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
nuxt, typescript
Domain
api, backend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.