How to fix You gave screen a query of type "query" but only "find" or "get" queries can be used with asynchronous assertions in React

ReactINTERMEDIATEMEDIUMUpdated Dec 11, 2025ยท 92 views

This error occurs when using React Testing Library's queryBy* methods with async assertions like waitFor or findBy*. queryBy* queries are designed for synchronous checks and return null when elements aren't found, while findBy* and getBy* queries handle async operations properly. Understanding the difference between query types prevents this common testing mistake.

Quick fix

Fixes You gave screen a query of type "query" but only "find" or "get" queries can be used with asynchronous assertions

// WRONG - queryBy* in waitFor
await waitFor(() => {
  expect(screen.queryByText("Loading...")).not.toBeInTheDocument();
});

// CORRECT - findBy* for async waiting
const loadingElement = await screen.findByText("Loading...");
expect(loadingElement).toBeInTheDocument();

// Also CORRECT - waitFor with getBy*
await waitFor(() => {
  expect(screen.getByText("Loading...")).toBeInTheDocument();
});
  1. Replace queryBy* with findBy* for async element waiting
  2. Use getBy* instead of queryBy* inside waitFor
  3. Reserve queryBy* for synchronous existence checks
  4. Understand the three query types and their use cases
react โ€” error
// WRONG - queryBy* in waitFor
await waitFor(() => {
expect(screen.queryByText("Loading...")).not.toBeInTheDocument();
});
// CORRECT - findBy* for async waiting
const loadingElement = await screen.findByText("Loading...");
expect(loadingElement).toBeInTheDocument();
// Also CORRECT - waitFor with getBy*
await waitFor(() => {
expect(screen.getByText("Loading...")).toBeInTheDocument();
});
You gave screen a query of type "query" but only "find" or "get" queries can be used with asynchronous assertions

What this error means

React Testing Library provides three main query types for finding elements: getBy*, queryBy*, and findBy*. Each serves a different purpose in testing scenarios. The error "You gave screen a query of type "query" but only "find" or "get" queries can be used with asynchronous assertions" occurs when you attempt to use a queryBy* method within an asynchronous assertion context. queryBy* queries are specifically designed for synchronous operations where you want to check if an element exists or doesn't exist without throwing an error. They return null when elements aren't found, making them unsuitable for async assertions that expect the query to wait for elements to appear. Async assertions like waitFor, findBy*, or async matchers require queries that will either find the element or throw an error, which is why only getBy* (synchronous error-throwing) and findBy* (async error-throwing) queries are allowed in these contexts.

Typical symptoms

  • Test fails with error: "You gave screen a query of type "query" but only "find" or "get" queries can be used with asynchronous assertions"
  • Tests using waitFor() with queryBy* queries fail unexpectedly
  • Async tests that should wait for elements to appear fail immediately
  • Test output shows the query type mismatch error during async operations
  • Tests pass when run synchronously but fail when wrapped in async assertions

Common causes

  1. Using queryBy* inside waitFor() function calls
  2. Mixing queryBy* with findBy* in async test patterns
  3. Incorrectly assuming queryBy* can be used for async element waiting
  4. Copy-pasting test code without understanding query type differences
  5. Using queryBy* with custom async matchers or expectations

How to fix "You gave screen a query of type "query" but only "find" or "get" queries can be used with asynchronous assertions"

1Replace queryBy* with findBy* for async element waiting

When you need to wait for an element to appear asynchronously (e.g., after API calls, state updates, or animations), use findBy* queries instead of queryBy*. findBy* queries combine getBy* with waitFor internally, automatically waiting for the element to appear.

typescript
// WRONG - queryBy* in waitFor
await waitFor(() => {
  expect(screen.queryByText("Loading...")).not.toBeInTheDocument();
});

// CORRECT - findBy* for async waiting
const loadingElement = await screen.findByText("Loading...");
expect(loadingElement).toBeInTheDocument();

// Also CORRECT - waitFor with getBy*
await waitFor(() => {
  expect(screen.getByText("Loading...")).toBeInTheDocument();
});
2Use getBy* instead of queryBy* inside waitFor

If you need to use waitFor explicitly, use getBy* queries inside it. getBy* queries throw errors when elements aren't found, which works correctly with waitFor's retry mechanism.

typescript
// WRONG
await waitFor(() => {
  expect(screen.queryByRole("button", { name: "Submit" })).toBeEnabled();
});

// CORRECT
await waitFor(() => {
  const button = screen.getByRole("button", { name: "Submit" });
  expect(button).toBeEnabled();
});

// Also CORRECT - findBy* is simpler
const button = await screen.findByRole("button", { name: "Submit" });
expect(button).toBeEnabled();
3Reserve queryBy* for synchronous existence checks

Use queryBy* only when you need to check if an element is NOT present, or when you want to conditionally assert without throwing errors. These are synchronous operations that don't involve waiting.

typescript
// CORRECT - queryBy* for checking element absence
const submitButton = screen.queryByRole("button", { name: "Submit" });
expect(submitButton).not.toBeInTheDocument();

// CORRECT - queryBy* for conditional logic
const errorMessage = screen.queryByText("Error occurred");
if (errorMessage) {
  // Handle error case
  expect(errorMessage).toHaveClass("error");
}

// WRONG - queryBy* with async waiting
await waitFor(() => {
  expect(screen.queryByText("Success!")).toBeInTheDocument();
});
4Understand the three query types and their use cases

Memorize the purpose of each query type to prevent future errors:

- getBy*: Use when you expect the element to be present NOW. Throws error if not found. Good for synchronous assertions.
- queryBy*: Use when checking if element is NOT present, or for conditional logic. Returns null if not found. Synchronous only.
- findBy*: Use when waiting for element to appear. Returns Promise that resolves when found, rejects if timeout. Async version of getBy*.

typescript
// Synchronous - element should be present
expect(screen.getByText("Welcome")).toBeInTheDocument();

// Synchronous - element should NOT be present
expect(screen.queryByText("Loading...")).not.toBeInTheDocument();

// Asynchronous - wait for element to appear
const data = await screen.findByTestId("user-data");
expect(data).toHaveTextContent("John Doe");
5Fix common async test patterns

Update these common patterns that incorrectly use queryBy*:

typescript
// Pattern 1: Waiting for element to disappear
// WRONG
await waitFor(() => {
  expect(screen.queryByText("Loading...")).not.toBeInTheDocument();
});

// CORRECT - waitFor with getBy* and .not
await waitFor(() => {
  expect(screen.getByText("Loading...")).not.toBeInTheDocument();
});

// Pattern 2: Multiple async checks
// WRONG
await waitFor(() => {
  expect(screen.queryByText("Step 1")).toBeInTheDocument();
  expect(screen.queryByText("Step 2")).toBeInTheDocument();
});

// CORRECT - findBy* for each or waitFor with getBy*
const step1 = await screen.findByText("Step 1");
const step2 = await screen.findByText("Step 2");
expect(step1).toBeInTheDocument();
expect(step2).toBeInTheDocument();

// OR
await waitFor(() => {
  expect(screen.getByText("Step 1")).toBeInTheDocument();
  expect(screen.getByText("Step 2")).toBeInTheDocument();
});
6Add proper async/await and error handling

Ensure your tests properly handle async operations and errors:

typescript
// WRONG - missing async/await
it("should load data", () => {
  userEvent.click(screen.getByText("Load"));
  // This will fail because queryBy* is in waitFor
  waitFor(() => {
    expect(screen.queryByText("Data loaded")).toBeInTheDocument();
  });
});

// CORRECT - proper async/await
it("should load data", async () => {
  userEvent.click(screen.getByText("Load"));
  // Use findBy* for async waiting
  const message = await screen.findByText("Data loaded");
  expect(message).toBeInTheDocument();
});

// CORRECT - with try/catch for error cases
it("should handle errors", async () => {
  userEvent.click(screen.getByText("Load"));
  try {
    await screen.findByText("Error occurred", { timeout: 2000 });
    // Error appeared as expected
  } catch (error) {
    // No error appeared within timeout
    fail("Expected error message to appear");
  }
});

Advanced notes

The query type system in React Testing Library is designed to make tests more explicit and prevent common mistakes. queryBy* queries return null instead of throwing errors to facilitate "element not present" assertions. This design choice means they cannot be used in async contexts where the test runner needs to distinguish between "element not found yet" (should retry) and "element will never be found" (should fail). Under the hood, findBy* queries use waitFor with getBy*, retrying until the element appears or a timeout occurs. When debugging async test failures, increase default timeouts carefully: screen.findBy*(..., { timeout: 5000 }). For complex async scenarios with multiple dependent elements, consider using waitFor with multiple getBy* assertions instead of multiple findBy* calls to avoid nested async operations. Remember that userEvent methods are async in newer versions of Testing Library, so always use await with them.

Frequently asked questions

What does "You gave screen a query of type "query" but only "find" or "get" queri" mean?
React Testing Library provides three main query types for finding elements: getBy, queryBy, and findBy. Each serves a different purpose in testing scenarios. The error "You gave screen a query of type "query" but only "find" or "get" queries can be used with asynchronous assertions" occurs when you attempt to use a queryBy method within an asynchronous assertion context.
How do I fix "You gave screen a query of type "query" but only "find" or "get" queri"?
This error occurs when using React Testing Library's queryBy methods with async assertions like waitFor or findBy. queryBy queries are designed for synchronous checks and return null when elements aren't found, while findBy and getBy* queries handle async operations properly. Understanding the difference between query types prevents this common testing mistake.
What causes "You gave screen a query of type "query" but only "find" or "get" queri"?
Using queryBy* inside waitFor() function calls Mixing queryBy with findBy in async test patterns Incorrectly assuming queryBy* can be used for async element waiting
Is the "You gave screen a query of type "query" but only "find" or "get" queri" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading