TanStack/query · warning · UnprocessableKeyError

In file ${filePath} at line ${node.loc.start.line} the \`${k

Error message

In file ${filePath} at line ${node.loc.start.line} the \`${keyName}\` couldn't be found. Did you forget to add it?

What it means

`UnprocessableKeyError` from `key-replacer.cjs` when the first argument to a query hook is an `ObjectExpression` (already an options object) but the expected key property (e.g. `queryKey`) is absent. The codemod cannot synthesize a key the developer never wrote, so it asks the user to add it manually.

Source

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

    if (methodArguments.length === 0) {
      return node
    }

    try {
      const [firstArgument, ...restOfTheArguments] = methodArguments

      if (
        jscodeshift.match(firstArgument, {
          type: jscodeshift.ObjectExpression.name,
        })
      ) {
        const originalKey = getPropertyFromObjectExpression(
          firstArgument,
          keyName,
        )

        if (!originalKey) {
          throw new UnprocessableKeyError(
            `In file ${filePath} at line ${node.loc.start.line} the \`${keyName}\` couldn't be found. Did you forget to add it?`,
          )
        }

        const restOfTheProperties = firstArgument.properties.filter(
          (item) => item.key.name !== keyName,
        )

        return buildWithTypeArguments(node, (originalNode) =>
          jscodeshift.callExpression(originalNode.original.callee, [
            jscodeshift.objectExpression([
              createKeyProperty(originalKey.value),
              ...restOfTheProperties,
            ]),
            ...restOfTheArguments,
          ]),
        )
      }

View on GitHub (pinned to 159982c80b)

Solutions

  1. Add the missing `queryKey` to the options object manually and re-run the codemod.
  2. Verify the property name matches what the codemod expects (`queryKey`, `mutationKey`, etc.).
  3. If the key is genuinely dynamic, declare it as an array literal at the call site.
  4. Skip the codemod for that file and migrate it by hand.

Example fix

// before
useQuery({ queryFn: fetchTodos })
// after (manual)
useQuery({ queryKey: ['todos'], queryFn: fetchTodos })
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-scan: does the options object contain the expected key property?
function hasKeyProperty(objectExpr: any, keyName: string): boolean {
  return objectExpr.properties.some((p: any) => p.key?.name === keyName)
}

Try / catch

try { transform(file) } catch (e) { if (/couldn't be found/.test(e.message)) missingKeyQueue.push(file) }

Prevention

When it happens

Trigger: A call like `useQuery({ queryFn: fetch, ... })` where `queryKey` was omitted; an options object whose key uses a different property name (typo, or `variables` from graphql-query); spread objects where the key is in a different fragment not visible to the codemod.

Common situations: Older code that did not require a `queryKey`; refactors that renamed the property; codemod run on partial migration; GraphQL-query wrappers using different property names.

Related errors


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