cocoindex-io/cocoindex · error · ValueError

from_table must be specified for polymorphic relations

Error message

from_table must be specified for polymorphic relations (possible tables: {self._from_table_names})

What it means

When declaring a relation on a polymorphic (multi-table) relation target, the source table cannot be inferred: there is no single default from-table, so `declare_relation` raises ValueError listing the candidate tables. The caller must name which table the relation originates from.

Solutions

  1. Pass `from_table=<TableTarget>` for one of the tables listed in the error message's `(possible tables: ...)`.
  2. If all relations truly come from one table, declare the relation target with that single from-table so a default exists.
  3. Check the possible-tables list in the message and use the exact table object/name.

Example fix

// before
await rel_target.declare_relation(record=edge, to_table=post_table)
// after
await rel_target.declare_relation(record=edge, from_table=user_table, to_table=post_table)
Defensive patterns

Strategy: validation

Validate before calling

if from_table is None and rel_target.default_from_table is None:
    raise ValueError("declare_relation requires from_table for polymorphic relation targets")

Type guard

def can_omit_from_table(rel_target) -> bool:
    return getattr(rel_target, "_default_from_table", None) is not None

Try / catch

try:
    await rel_target.declare_relation(record=rec, to_table=dst)
except ValueError as e:
    if "from_table must be specified" in str(e):
        await rel_target.declare_relation(record=rec, from_table=src, to_table=dst)
    else:
        raise

Prevention

When it happens

Trigger: Calling `declare_relation(...)` without `from_table=...` on a relation target whose `_default_from_table` is None (multiple from-tables were declared).

Common situations: Graph-style schemas where edges can start from several node tables (User, Post, Comment); forgetting that polymorphic relations require explicit endpoints.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of cocoindex-io/cocoindex@e84aa99b32 (2026-09-08). Data as JSON: /api/errors/05852d7634e89530. Report an issue: GitHub.

Appendix: source

Thrown at python/cocoindex/connectors/surrealdb/_target.py:1206

        self._default_to_table = to_table_names[0] if len(to_table_names) == 1 else None

    def declare_relation(
        self: RelationTarget[RowT],
        *,
        from_id: Any,
        to_id: Any,
        record: RowT | None = None,
        from_table: TableTarget[Any] | None = None,
        to_table: TableTarget[Any] | None = None,
    ) -> None:
        """Declare a relation record."""
        # Resolve from_table_name
        if from_table is not None:
            from_table_name = from_table.table_name
        elif self._default_from_table is not None:
            from_table_name = self._default_from_table
        else:
            raise ValueError(
                "from_table must be specified for polymorphic relations "
                f"(possible tables: {self._from_table_names})"
            )

        # Resolve to_table_name
        if to_table is not None:
            to_table_name = to_table.table_name
        elif self._default_to_table is not None:
            to_table_name = self._default_to_table
        else:
            raise ValueError(
                "to_table must be specified for polymorphic relations "
                f"(possible tables: {self._to_table_names})"
            )

        # Build the value dict from the record (exclude 'id' — it's the key, not content)
        if record is not None:
            if self._table_schema is not None:

View on GitHub (pinned to e84aa99b32)