VectifyAI/PageIndex · error · PageIndexAPIError

chat must be a string or a dict.

Error message

chat must be a string or a dict.

What it means

The chat argument was neither a string, a dict/Mapping, nor None — e.g. a list, int, or object. The SDK validates chat's type up front because each type spells a different configuration shape.

Source

Thrown at pageindex/client.py:221

        unknown = set(conf) - {"model", "backend"}
        if (not conf and declared is None) or unknown:
            raise PageIndexAPIError(
                ("chat is an empty dict" if not conf else
                 f"Unknown chat keys ({', '.join(sorted(unknown))})")
                + ' — chat takes "model" and "backend" (your own model), '
                'or {"mode": "cloud"} / "cloud" for the managed chat.')
        if declared == "cloud":
            if conf:
                raise PageIndexAPIError(
                    'chat declares mode "cloud" but carries '
                    f"({', '.join(sorted(conf))}) — the managed chat "
                    "selects its own model. Drop the mode, or the keys.")
            return "managed", {}
        mapped = {"chat_model": conf.get("model"),
                  "chat_backend": conf.get("backend")}
        return "own", {name: value for name, value in mapped.items()
                       if value is not None}
    raise PageIndexAPIError("chat must be a string or a dict.")


class PageIndexClient:
    """
    Python SDK client for PageIndex.

    Two independent sides, each locally run or cloud-managed:

    - **index** — where documents live. With an ``api_key`` they live in
      your PageIndex cloud account, indexed by the managed pipeline,
      exactly like the 0.2.x SDK. Without one they are indexed on your
      machine by the open-source pipeline (your own LLM provider key,
      e.g. ``OPENAI_API_KEY``) and stored under ``storage_path``.
    - **chat** — who answers. With a chat model configured
      (``chat_model=`` / ``chat=``), the document-QA agent runs in your
      process against your own model and credentials — in both index
      modes. On a cloud client with no chat model, the managed cloud
      chat answers.

View on GitHub (pinned to afb5e11976)

Solutions

  1. Pass the model name as a string: chat="gpt-4o-mini"
  2. Or pass a config dict: chat={"model": ..., "backend": ...}
  3. Provider client instances go inside the backend config, not as chat itself

Example fix

# before
PageIndexClient(chat=["gpt-4o-mini"])
# after
PageIndexClient(chat="gpt-4o-mini")
Defensive patterns

Strategy: type-guard

Type guard

def valid_chat(chat) -> bool:
    return chat is None or isinstance(chat, (str, dict))

Prevention

When it happens

Trigger: PageIndexClient(chat=["gpt-4o-mini"]), chat=42, chat=True, or passing a model object instead of its name.

Common situations: Passing a list of model names expecting fallback behavior; passing an SDK client object (e.g. an OpenAI client) where only a config dict or name string is accepted; booleans from feature flags.

Understand the failure class

Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.

Related errors


AI-assisted analysis of VectifyAI/PageIndex@afb5e11976 (2026-08-27). Data as JSON: /api/errors/d4fe902294aa0326. Report an issue: GitHub.