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
- Pass `from_table=<TableTarget>` for one of the tables listed in the error message's `(possible tables: ...)`.
- If all relations truly come from one table, declare the relation target with that single from-table so a default exists.
- 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
- Always pass explicit from_table/to_table when the relation target has multiple node tables.
- Read the possible-tables list from the error message to pick a valid table.
- Keep relation declarations next to table declarations so endpoints are obvious.
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
- to_table must be specified for polymorphic relations
- dimension is required for declare_vector_index()
- Invalid vector dimension
- record_type must be a record type (dataclass, NamedTuple…
- aiobotocore is required to use the Amazon S3 source…
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)