hasura/graphql-engine · error · ErrorWithStatusCode

`escapeTargetName` only implemented for tables and interpola

Error message

`escapeTargetName` only implemented for tables and interpolated queries

What it means

escapeTargetName switches on the target type and only knows how to escape `'table'` and `'interpolated'` targets (the latter via its CTE id). Any other target type — in practice `'function'` — falls into the default branch and throws an ErrorWithStatusCode(500).

Source

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

}

/**
 *
 * @param tableName: Unescaped table name. E.g. 'Alb"um'
 * @returns Escaped table name. E.g. '"Alb\"um"'
 */
export function escapeTableName(tableName: TableName): string {
  return validateTableName(tableName).map(escapeIdentifier).join('.');
}

export function escapeTargetName(target: Target): string {
  switch (target.type) {
    case 'table':
      return escapeTableName(target.name);
    case 'interpolated':
      return escapeTableName([target.id]); // Interpret as CTE reference
    default:
      throw new ErrorWithStatusCode(
        '`escapeTargetName` only implemented for tables and interpolated queries',
        500,
        { target },
      );
  }
}

/**
 * @param tableName
 * @returns escaped tableName string with schema qualification removed
 *
 * This is useful in where clauses in returning statements where a qualified table name is invalid SQLite SQL.
 */
export function escapeTableNameSansSchema(tableName: TableName): string {
  return escapeTableName(getTableNameSansSchema(tableName));
}

export function json_object(

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Ensure every target in the request tree (including nested/relationship targets) is a table or interpolated target
  2. Upgrade the agent — function targets should be rejected earlier with a clearer message
  3. If you control the server, extend escapeTargetName rather than letting it hit default

Example fix

// before: nested function target
{ type: 'function', name: 'udf' }
// after
{ type: 'table', name: ['main','public','materialized_view'] }
Defensive patterns

Strategy: validation

Validate before calling

function assertQueryableTargetTree(q: any) { walk(q, t => { if (t?.type !== 'table' && t?.type !== 'interpolated') throw new Error(`Unsupported target: ${t?.type}`); }); }

Type guard

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

Prevention

When it happens

Trigger: A query with a function target reaching WHERE-clause, subquery, join, or aggregate-subquery generation because it bypassed the earlier top-level type check (e.g. nested inside a relationship or reused target object).

Common situations: Function targets sneaking in through relationship traversal or nested query fragments rather than the top-level body; version drift between the request schema and the query builder's supported target kinds.

Related errors


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