hasura/graphql-engine · error · ErrorWithStatusCode

Can't execute table_query for UDFs

Error message

Can't execute table_query for UDFs

What it means

target_query is the core SELECT/subquery builder and only handles table and interpolated targets. A target of type 'function' is rejected with ErrorWithStatusCode(500) because a UDF call cannot serve as the FROM-clause source of a table query. Reached from relationship expansion, result building, and table subqueries.

Source

Thrown at dc-agents/sqlite/src/query.ts:511

  aggregates: Aggregates | null,
  wWhere: Expression | null,
  aggregatesLimit: number | null,
  wLimit: number | null,
  wOffset: number | null,
  wOrder: OrderBy | null,
): string {
  var tableName;

  // TableNames are resolved from IDs when using NQs.
  switch (target.type) {
    case 'table':
      tableName = target.name;
      break;
    case 'interpolated':
      tableName = [target.id];
      break;
    case 'function':
      throw new ErrorWithStatusCode(`Can't execute table_query for UDFs`, 500, {
        target,
      });
  }

  const tableAlias = generateTargetAlias(target);
  const aggregateSelect = aggregates
    ? [
        aggregates_query(
          allRelationships,
          target,
          joinInfo,
          aggregates,
          wWhere,
          aggregatesLimit,
          wOffset,
          wOrder,
        ),
      ]

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Use only table/interpolated targets everywhere in the request tree
  2. Pre-validate the request tree client-side to reject function targets before the call
  3. Materialize the function's output into a table or view

Example fix

// before
{ target: { type: 'function', name: 'recent_orders' }, ... }
// after
{ target: { type: 'table', name: ['main','public','recent_orders'] }, ... }
Defensive patterns

Strategy: validation

Validate before calling

if (body.target.type === 'function') throw new Error('SQLite agent cannot execute table_query for UDFs');

Type guard

const isQueryableTarget = (t: Target): t is TableTarget | InterpolatedTarget => t.type === 'table' || t.type === 'interpolated';

Prevention

When it happens

Trigger: A function target reaching the main query builder — top level, via a relationship's target, or via a subquery — after passing the earlier endpoint-level check.

Common situations: Nested function targets inside relationship trees; generic client code wrapping entities as function targets; API version drift.

Related errors


AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28). Data as JSON: /api/errors/79950055dc20f50a. Report an issue: GitHub.