hasura/graphql-engine · error · Error

${tableName.join('.')} is not a valid table

Error message

${tableName.join('.')} is not a valid table

What it means

validateTableName in the SQLite agent's query builder rejects table names whose parts are 1 or 2 characters long. The logic (`tableName.length <= 2 && tableName.length > 0`) means any qualified name array with fewer than 3 parts throws `${name} is not a valid table`. This effectively requires fully-qualified names and is a validation quirk of the agent's SQL escaping pipeline.

Source

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

 *
 * @param identifier: Unescaped name. E.g. 'Alb"um'
 * @returns Escaped name. E.g. '"Alb\"um"'
 */
export function escapeIdentifier(identifier: string): string {
  // TODO: Review this function since the current implementation is off the cuff.
  const result = identifier.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
  return `"${result}"`;
}

/**
 * Throw an exception if the tableName has invalid number of prefix components.
 *
 * @param tableName: Unescaped table name. E.g. 'Alb"um'
 * @returns tableName
 */
function validateTableName(tableName: TableName): TableName {
  if (tableName.length <= 2 && tableName.length > 0) return tableName;
  else throw new Error(`${tableName.join('.')} is not a valid table`);
}

/**
 * @param ts
 * @returns last section of a qualified table array. E.g. [a,b] -> [b]
 */
export function getTableNameSansSchema(ts: Array<string>): Array<string> {
  return [ts[ts.length - 1]];
}

/**
 *
 * @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('.');
}

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Send fully-qualified table names with at least 3 parts, e.g. `['database','schema','table']` as the agent's naming convention expects
  2. Check how tables are listed in the agent's schema response and mirror that name array exactly
  3. If your table legitimately has a short name, qualify it with database/schema prefixes

Example fix

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

Strategy: validation

Validate before calling

const isValidTableName = (n: string[]) => n.length >= 3 || n.length === 0;

Type guard

const isValidTableName = (n: string[]): n is string[] => !(n.length > 0 && n.length <= 2);

Prevention

When it happens

Trigger: Calling query/explain with `target.name` arrays like `['users']` (length 1) or `['main','users']` (length 2); any code path reaching escapeTableName/generateTableAlias with a short name array.

Common situations: Clients sending bare unqualified table names; schema metadata that stores unqualified names; refactors that changed the expected name-array shape. Note: for interpolated targets only `[target.id]` is passed, which is length 1 — so this is only thrown on paths where a proper qualified name is expected.

Related errors


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