langfuse/langfuse · error · InvalidRequestError

Invalid relationTable: ${relationTableName}. Must be one of

Error message

Invalid relationTable: ${relationTableName}. Must be one of ${Object.keys(view.tableRelations)}

What it means

Thrown by buildJoins when a query requests a relation table that is not registered in view.tableRelations for the current entity. The join layer only knows a fixed set of relation tables per view.

Source

Thrown at packages/shared/src/features/query/server/queryBuilder.ts:803

    // Replace each @@AGGN@@ placeholder with its corresponding value
    for (const [placeholder, replacement] of Object.entries(aggs)) {
      const marker = `@@${placeholder.toUpperCase()}@@`;
      result = result.replaceAll(marker, replacement);
    }
    return result;
  }

  private buildJoins(
    relationTables: Set<string>,
    view: ViewDeclarationType,
    filterList: FilterList,
    query: QueryType,
    skipObservationsFinal: boolean,
  ) {
    const relationJoins = [];
    for (const relationTableName of relationTables) {
      if (!(relationTableName in view.tableRelations)) {
        throw new InvalidRequestError(
          `Invalid relationTable: ${relationTableName}. Must be one of ${Object.keys(view.tableRelations)}`,
        );
      }

      const relation = view.tableRelations[relationTableName];
      // Conditionally add FINAL - skip for observations if flag is set, and respect per-relation useFinal
      const shouldUseFinal =
        (relation.useFinal ?? true) &&
        !(relation.name === "observations" && skipObservationsFinal);
      const alias =
        relation.name !== relationTableName ? ` AS ${relationTableName}` : "";
      let joinStatement = `INNER JOIN ${relation.name}${alias}${shouldUseFinal ? " FINAL" : ""} ${relation.joinConditionSql}`;

      // Create time dimension mapping for the relation table
      const relationTimeDimensionMapping = {
        uiTableName: relation.timeDimension,
        uiTableId: relation.timeDimension,
        clickhouseTableName: relation.name,

View on GitHub (pinned to 59d92c7cf3)

Solutions

  1. Use only relation names listed in the error (Object.keys(view.tableRelations))
  2. Construct queries via the provided helper functions rather than assembling relationTables manually
Defensive patterns

Strategy: validation

Validate before calling

const valid = new Set(Object.keys(view.tableRelations));
const safe = relationTables.filter(r => valid.has(r));

Type guard

const isValidRelationTable = (r: string, view: QueryView) => r in view.tableRelations;

Prevention

When it happens

Trigger: Passing relationTables containing an unknown table name (e.g. "scores" on a view whose tableRelations lacks it) into QueryBuilder.build.

Common situations: Hand-constructing QueryBuilder options instead of using helper constructors; version skew where a relation exists in one view but not another; typos in relation names.

Related errors


AI-assisted analysis of langfuse/langfuse@59d92c7cf3 (2026-08-27). Data as JSON: /api/errors/b8942582e4c45009. Report an issue: GitHub.