vercel/ai · error

You can't get the "${String(key)}" field from the AI state b

Error message

You can't get the "${String(key)}" field from the AI state because it's not an object.

What it means

In the RSC package, getAIState(key) accepts an optional key to read a single field of the AI state. If a key is passed but the current AI state is not an object (e.g. null, a primitive, or an array held as scalar), reading a field is meaningless, so the library throws with a message naming the offending key.

Source

Thrown at packages/rsc/src/ai-state.tsx:84

 * @example const field = getAIState('key') // Get the value of the key
 */
function getAIState<AI extends AIProvider = any>(): Readonly<
  InferAIState<AI, any>
>;
function getAIState<AI extends AIProvider = any>(
  key: keyof InferAIState<AI, any>,
): Readonly<InferAIState<AI, any>[typeof key]>;
function getAIState<AI extends AIProvider = any>(
  ...args: [] | [key: keyof InferAIState<AI, any>]
) {
  const store = getAIStateStoreOrThrow(
    '`getAIState` must be called within an AI Action.',
  );

  if (args.length > 0) {
    const key = args[0];
    if (typeof store.currentState !== 'object') {
      throw new Error(
        `You can't get the "${String(
          key,
        )}" field from the AI state because it's not an object.`,
      );
    }
    return store.currentState[key as keyof typeof store.currentState];
  }

  return store.currentState;
}

/**
 * Get the mutable AI state. Note that you must call `.done()` when finishing
 * updating the AI state.
 *
 * @example
 * ```tsx
 * const state = getMutableAIState()

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Initialize the AI state as an object, e.g. { messages: [] } rather than [] or a scalar.
  2. Call getAIState() without a key if you want the whole state, then narrow it yourself.
  3. Check that no action replaces the entire state with a non-object via setAIState/mutable update.
  4. Add a runtime check `typeof state === 'object' && state !== null` before accessing keyed state.

Example fix

// before
// initial AI state: 0
const score = getAIState('score');

// after
// initial AI state: { score: 0 }
const { score } = getAIState();
Defensive patterns

Strategy: type-guard

Validate before calling

const state = getAIState();
if (state === null || typeof state !== 'object') {
  throw new Error('AI state must be an object before keyed access');
}
const value = (state as Record<string, unknown>).myKey;

Type guard

function isObjectState(s: unknown): s is Record<string, unknown> {
  return typeof s === 'object' && s !== null && !Array.isArray(s);
}

Try / catch

let value: unknown;
try {
  value = getAIState('myKey');
} catch (e) {
  if (e instanceof Error && e.message.includes("from the AI state because it's not an object")) {
    value = getAIState(); // fall back to whole-state read
  } else throw e;
}

Prevention

When it happens

Trigger: Calling getAIState('someKey') inside an AI Action when the state was initialized as a non-object (e.g. getAIState() of a number/string/null state set via an initial AIState of a primitive) — or after an action replaced the whole state with a non-object.

Common situations: Initializing useAIState/AI state with a scalar or null and later reading a named field; a setter action overwrote state with a primitive; typo assuming state shape differs from what was stored.

Related errors


AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30). Data as JSON: /api/errors/1a4ce8eb18b039a7. Report an issue: GitHub.