Skip to content

bug: Late errors for negative offset or limit query parameters #7474

Description

@ogenstad

Component

API Server / GraphQL

Infrahub version

1.4.12

Current Behavior

When issuing a query with negative offset or limit parameters we allow these through to the DB layer.

Expected Behavior

The error should be returned before reaching the database and report a user friendly error, i.e the graphql resolver should validate the input and raise an error.

Steps to Reproduce

  1. Issue a query with a negative offset and or limit:
query MyQuery {
  BuiltinTag(limit: -1, offset: -1) {
    edges {
      node {
        name {
          value
        }
      }
    }
  }
}
  1. Note the response to the client:
{
  "data": null,
  "errors": [
    {
      "message": "Invalid input. '-1' is not a valid value. Must be a non-negative integer. (line 20, column 7 (offset: 1194))\n\"LIMIT -1\"\n       ^",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "BuiltinTag"
      ]
    }
  ]
}
  1. We can also observe these logs on the server:
Traceback (most recent call last):
  File "/Users/patrick/.virtualenvs/infrahub/lib/python3.12/site-packages/graphql/execution/execute.py", line 530, in await_result
    return_type, field_nodes, info, path, await result
                                          ^^^^^^^^^^^^
  File "/Users/patrick/.virtualenvs/infrahub/lib/python3.12/site-packages/opentelemetry/util/_decorator.py", line 69, in async_wrapper
    return await func(*args, **kwargs)  # type: ignore
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/patrick/Code/opsmill/infrahub/backend/infrahub/graphql/resolvers/resolver.py", line 188, in default_paginated_list_resolver
    objs = await NodeManager.query(
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/patrick/Code/opsmill/infrahub/backend/infrahub/core/manager.py", line 188, in query
    await query.execute(db=db)
  File "/Users/patrick/.virtualenvs/infrahub/lib/python3.12/site-packages/opentelemetry/util/_decorator.py", line 69, in async_wrapper
    return await func(*args, **kwargs)  # type: ignore
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/patrick/Code/opsmill/infrahub/backend/infrahub/core/query/__init__.py", line 539, in execute
    results = await db.execute_query(
              ^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/patrick/Code/opsmill/infrahub/backend/infrahub/database/__init__.py", line 334, in execute_query
    results, _ = await self.execute_query_with_metadata(
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/patrick/Code/opsmill/infrahub/backend/infrahub/database/__init__.py", line 398, in execute_query_with_metadata
    response = await self.run_query(query=query, params=params, name=name)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/patrick/Code/opsmill/infrahub/backend/infrahub/database/__init__.py", line 420, in run_query
    response = await execution_method.run(query=_query, parameters=params)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/patrick/.virtualenvs/infrahub/lib/python3.12/site-packages/neo4j/_async/work/session.py", line 328, in run
    await self._auto_result._run(
  File "/Users/patrick/.virtualenvs/infrahub/lib/python3.12/site-packages/neo4j/_async/work/result.py", line 236, in _run
    await self._attach()
  File "/Users/patrick/.virtualenvs/infrahub/lib/python3.12/site-packages/neo4j/_async/work/result.py", line 430, in _attach
    await self._connection.fetch_message()
  File "/Users/patrick/.virtualenvs/infrahub/lib/python3.12/site-packages/neo4j/_async/io/_common.py", line 195, in inner
    await coroutine_func(*args, **kwargs)
  File "/Users/patrick/.virtualenvs/infrahub/lib/python3.12/site-packages/neo4j/_async/io/_bolt.py", line 864, in fetch_message
    res = await self._process_message(tag, fields)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/patrick/.virtualenvs/infrahub/lib/python3.12/site-packages/neo4j/_async/io/_bolt5.py", line 1208, in _process_message
    await response.on_failure(summary_metadata or {})
  File "/Users/patrick/.virtualenvs/infrahub/lib/python3.12/site-packages/neo4j/_async/io/_common.py", line 254, in on_failure
    raise self._hydrate_error(metadata)
neo4j.exceptions.CypherSyntaxError: {code: Neo.ClientError.Statement.SyntaxError} {message: Invalid input. '-1' is not a valid value. Must be a non-negative integer. (line 20, column 7 (offset: 1194))
"LIMIT -1"
       ^}

Additional Information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    type/bugSomething isn't working as expectedtype/newcomersGood for newcomers

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions