VectifyAI/PageIndex · error · PageIndexAPIError

chat is an empty dict — chat takes "model" and "backend" (yo

Error message

chat is an empty dict — chat takes "model" and "backend" (your own model), or {"mode": "cloud"} / "cloud" for the managed chat.

What it means

chat was given as a dict but, after dropping None-valued keys and any mode key, nothing remained to configure. The dict form exists to carry "model"/"backend" (or {"mode": "cloud"}); an effectively empty dict declares no chat at all, which the SDK treats as a mistake rather than silently ignoring it.

Source

Thrown at pageindex/client.py:205

        if word == "local":
            return "own", {}
        if word in _RESERVED_MODE_WORDS:
            raise PageIndexAPIError(
                f'chat="{chat}" is not a mode word — the managed chat is '
                'chat="cloud".')
        if chat.strip():
            return "own", {"chat_model": chat}
        raise PageIndexAPIError(
            "chat is an empty string — pass a model name, or "
            '"cloud" for the managed chat.')
    if isinstance(chat, Mapping):
        # None-valued keys mean "absent", exactly like the flat arguments.
        conf = {name: value for name, value in chat.items()
                if value is not None}
        declared = _declared_mode(conf.pop("mode", None), "chat")
        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.")

View on GitHub (pinned to afb5e11976)

Solutions

  1. Populate the dict with "model" and/or "backend": chat={"model": "gpt-4o-mini", "backend": {...}}
  2. Use {"mode": "cloud"} for the managed chat
  3. Remove the chat= argument entirely if no chat config is intended
  4. Filter None values before passing so an all-None dict becomes chat=None

Example fix

# before
PageIndexClient(chat={"model": cfg.get("model")})  # cfg has no model → {"model": None}
# after
PageIndexClient(chat={k: v for k, v in cfg.items() if v is not None} or None)
Defensive patterns

Strategy: validation

Validate before calling

chat_conf = {k: v for k, v in raw_chat.items() if v is not None} if isinstance(raw_chat, dict) else raw_chat
if chat_conf == {}:
    chat_conf = None
client = PageIndexClient(chat=chat_conf)

Type guard

def chat_dict_ok(d: dict) -> bool:
    return bool({k: v for k, v in d.items() if v is not None and k != "mode"}) or d.get("mode") is not None

Prevention

When it happens

Trigger: PageIndexClient(chat={}), chat={"model": None}, chat={"mode": None}, or chat built from a config dict whose keys are all None.

Common situations: Forwarding a YAML/JSON config block where chat: is present but empty or only has null fields; merging dicts that filtered out all real values.

Related errors


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