TanStack/query · warning · AlreadyHasPlaceholderDataProperty

The usage in file "${filePath}" at line ${start}:${end} alre

Error message

The usage in file "${filePath}" at line ${start}:${end} already contains a "placeholderData" property. Please migrate this usage manually.

What it means

`AlreadyHasPlaceholderDataProperty` thrown by the v5 `keep-previous-data` codemod. The transform converts `keepPreviousData: true` into `placeholderData: keepPreviousData`, but if the target options object already has a `placeholderData` property, overwriting it would silently change behavior, so the codemod refuses and asks for manual migration.

Source

Thrown at packages/query-codemods/src/v5/keep-previous-data/keep-previous-data.cjs:102

  const getKeepPreviousDataProperty = (objectExpression) => {
    return objectExpression.properties.find(isKeepPreviousDataObjectProperty)
  }

  let shouldAddKeepPreviousDataImport = false

  const replacer = (path, resolveTargetArgument, transformNode) => {
    const node = path.node
    const { start, end } = getNodeLocation(node)

    try {
      const targetArgument = resolveTargetArgument(node)

      if (targetArgument && utils.isObjectExpression(targetArgument)) {
        const isPlaceholderDataPropertyPresent =
          hasPlaceholderDataProperty(targetArgument)

        if (hasPlaceholderDataProperty(targetArgument)) {
          throw new AlreadyHasPlaceholderDataProperty(node, filePath)
        }

        const keepPreviousDataProperty =
          getKeepPreviousDataProperty(targetArgument)

        const keepPreviousDataPropertyHasTrueValue =
          isObjectPropertyHasTrueBooleanLiteralValue(keepPreviousDataProperty)

        if (!keepPreviousDataPropertyHasTrueValue) {
          utils.warn(
            `The usage in file "${filePath}" at line ${start}:${end} already contains a "keepPreviousData" property but its value is not "true". Please migrate this usage manually.`,
          )

          return node
        }

        if (keepPreviousDataPropertyHasTrueValue) {
          // Removing the `keepPreviousData` property from the object.

View on GitHub (pinned to 159982c80b)

Solutions

  1. Inspect the cited file:line and decide which placeholder behavior you want in v5.
  2. Manually replace `keepPreviousData: true` with `placeholderData: keepPreviousData` (imported from `@tanstack/react-query`) and remove the conflicting `placeholderData` value, OR keep your existing `placeholderData` and remove `keepPreviousData`.
  3. Re-run the codemod to transform the remaining call sites.
  4. Add a regression test verifying the placeholder behavior after migration.

Example fix

// before
useQuery({ queryKey, queryFn, keepPreviousData: true, placeholderData: oldValue })
// after (manual)
import { keepPreviousData } from '@tanstack/react-query'
useQuery({ queryKey, queryFn, placeholderData: keepPreviousData })
Defensive patterns

Strategy: try-catch

Validate before calling

// Detect pre-existing placeholderData before running the codemod.
function hasPlaceholderDataProp(objectExpr: any): boolean {
  return objectExpr.properties.some((p: any) => p.key?.name === 'placeholderData')
}

Try / catch

try { runKeepPreviousDataCodemod(file) } catch (e) { if (e.name === 'AlreadyHasPlaceholderDataProperty') manualQueue.push({ file, loc: e.message }) }

Prevention

When it happens

Trigger: A v4 query that uses BOTH `keepPreviousData: true` AND `placeholderData: ...`; running the `keep-previous-data` codemod on such a call site.

Common situations: Codebases that combined both options in v4 to layer placeholder behavior; partial migration where `placeholderData` was already added; copied examples that included both flags.

Related errors


AI-assisted analysis of TanStack/query@159982c80b (2026-08-12). Data as JSON: /api/errors/2cc9c4089908f896. Report an issue: GitHub.