TanStack/query · warning · UnprocessableKeyError

In file ${filePath} at line ${node.loc.start.line} the type

Error message

In file ${filePath} at line ${node.loc.start.line} the type of identifier \`${node.name}\` couldn't be recognized, so the codemod couldn't be applied. Please migrate manually.

What it means

`UnprocessableKeyError` from the v4 codemod's `key-replacer.cjs`. When the AST node for a query key is an `Identifier`, the codemod tries to find its `const` declaration (`findVariableDeclaration`) to guess the type. If no declaration is found (e.g. a parameter, an import, or a destructured binding), it cannot safely transform and throws with the file path and line number for manual migration.

Source

Thrown at packages/query-codemods/src/v4/utils/replacers/key-replacer.cjs:53

      return jscodeshift.arrayExpression([
        jscodeshift.stringLiteral(node.value),
      ])
    }

    // When the node is a template literal we convert it into an array of template literals.
    if (isTemplateLiteral(node)) {
      return jscodeshift.arrayExpression([
        jscodeshift.templateLiteral(node.quasis, node.expressions),
      ])
    }

    if (jscodeshift.match(node, { type: jscodeshift.Identifier.name })) {
      // When the node is an identifier at first, we try to find its declaration, because we will try
      // to guess its type.
      const variableDeclaration = findVariableDeclaration(node)

      if (!variableDeclaration) {
        throw new UnprocessableKeyError(
          `In file ${filePath} at line ${node.loc.start.line} the type of identifier \`${node.name}\` couldn't be recognized, so the codemod couldn't be applied. Please migrate manually.`,
        )
      }

      const initializer = variableDeclaration.value.init

      // When it's a string, we just wrap it into an array expression.
      if (isStringLiteral(initializer) || isTemplateLiteral(initializer)) {
        return jscodeshift.arrayExpression([node])
      }
    }

    throw new UnprocessableKeyError(
      `In file ${filePath} at line ${node.loc.start.line} the type of the \`${keyName}\` couldn't be recognized, so the codemod couldn't be applied. Please migrate manually.`,
    )
  }

  const createKeyProperty = (node) =>

View on GitHub (pinned to 159982c80b)

Solutions

  1. Open the cited file:line and convert the query key to a literal array or template literal so the codemod can handle it, then re-run.
  2. Manually wrap the identifier: `useQuery([myKey], ...)` -> `useQuery({ queryKey: [myKey], queryFn: ... })`.
  3. Hoist the identifier into a `const` array literal near the call site so the codemod finds its declaration.
  4. Re-run the codemod on the fixed file and verify other call sites still transform.

Example fix

// before
useQuery(myKey, fetchFn)
// after (manual)
useQuery({ queryKey: [myKey], queryFn: fetchFn })
Defensive patterns

Strategy: try-catch

Validate before calling

// Codemod-side: pre-scan for identifiers without findable declarations.
function hasSimpleDeclaration(scope: any, name: string): boolean {
  const node = scope.lookup(name)
  return !!node && node.value?.init
}

Try / catch

// Drive the codemod and collect failures for manual review.
const report = []
for (const file of files) {
  try { runCodemod(file) }
  catch (e) { if (e.name === 'UnprocessableKeyError') report.push({ file, message: e.message }) }
}

Prevention

When it happens

Trigger: Running the v4 codemod on code where the query key is an identifier whose declaration is not a simple `const x = ...` in scope: function parameters, imported bindings, destructured variables, properties (`obj.key`), loop variables, or identifiers declared with `let`/`var` in a different block.

Common situations: Migrating a large v3->v4 codebase with non-trivial key indirection; codemod applied to partial files; keys computed from props/parameters in shared hooks; older codebases with `var` declarations.

Related errors


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