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
- Send fully-qualified table names with at least 3 parts, e.g. `['database','schema','table']` as the agent's naming convention expects
- Check how tables are listed in the agent's schema response and mirror that name array exactly
- 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
- Always send fully-qualified name arrays as the agent's schema endpoint reports them
- Never hand-construct short name arrays for tables (single-part arrays are reserved for interpolated ids)
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
- `escapeTargetName` only implemented for tables and interpola
- Couldn't find relationship ${field.relationship} for field $
- Unsupported field type "object"
- Unsupported field type "array"
- Unsupported path on ComparisonColumn: ${[...path, selector].
AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28).
Data as JSON: /api/errors/20dcddbc361fa50f.
Report an issue: GitHub.