langchain-ai/langgraph · error · ValueError

Text fields must be a list or a string. Got

Error message

Text fields must be a list or a string. Got {fields}

What it means

Thrown by _ensure_index_config during Postgres store initialization: the 'fields' entry of index_config (the text fields to index for search) is neither a string nor a list. The guard runs after the falsy default (['$']) and string normalization, so the value at fault is typically a dict, int, tuple, or None-like non-falsy object of another type.

Solutions

  1. Set index_config['fields'] to a list of JSON-path strings, e.g. ['$', 'summary'] or ['$', 'attributes.role']
  2. Use the shorthand string form '$' to index the whole document as text
  3. Remove the 'fields' key entirely to accept the default ['$']
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at libs/checkpoint-postgres/langgraph/store/postgres/base.py:1463 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of langchain-ai/langgraph@38031739e5 (2026-08-26). Data as JSON: /api/errors/9635fb88296d1a2c. Report an issue: GitHub.

Appendix: source

Thrown at libs/checkpoint-postgres/langgraph/store/postgres/base.py:1463

    elif distance_type == "inner_product":
        # Final: "-(sv.embedding <#> %s::%s)"
        return "sv.embedding <#> %s::%s", "-(scored.neg_score)"
    else:  # cosine similarity
        # Final:  "1 - (sv.embedding <=> %s::%s)"
        return "sv.embedding <=> %s::%s", "1 - scored.neg_score"


def _ensure_index_config(
    index_config: PostgresIndexConfig,
) -> tuple[Embeddings | None, PostgresIndexConfig]:
    index_config = index_config.copy()
    tokenized: list[tuple[str, Literal["$"] | list[str]]] = []
    tot = 0
    fields = index_config.get("fields") or ["$"]
    if isinstance(fields, str):
        fields = [fields]
    if not isinstance(fields, list):
        raise ValueError(f"Text fields must be a list or a string. Got {fields}")
    for p in fields:
        if p == "$":
            tokenized.append((p, "$"))
            tot += 1
        else:
            toks = tokenize_path(p)
            tokenized.append((p, toks))
            tot += len(toks)
    index_config["__tokenized_fields"] = tokenized
    index_config["__estimated_num_vectors"] = tot
    embeddings = ensure_embeddings(
        index_config.get("embed"),
    )
    return embeddings, index_config


PLACEHOLDER = object()

View on GitHub (pinned to 38031739e5)