hasura/graphql-engine · error · Error
Encountered a non-statement or non-list DDL for table.
Error message
Encountered a non-statement or non-list DDL for table.
What it means
Same AST shape check as getColumnsDdl, applied when extracting FOREIGN KEY constraints from parsed DDL (ddlFKs, feeding the foreignKeys flow). If sqlite-parser's output for a table's DDL is not a statement list, FK introspection aborts with this error, which usually kills the whole schema request.
Source
Thrown at dc-agents/sqlite/src/schema.ts:227
* },
* foreign_table: "Artist",
* }
* }
*
* NOTE: We currently don't log if the structure of the DDL is unexpected, which could be the case for composite FKs, etc.
* NOTE: There could be multiple paths between tables.
* NOTE: Composite keys are not currently supported.
*
* @param ddl
* @returns [name, FK constraint definition][]
*/
function ddlFKs(
config: Config,
tableName: Array<string>,
ddl: any,
): [string, Constraint][] {
if (ddl.type != 'statement' || ddl.variant != 'list') {
throw new Error('Encountered a non-statement or non-list DDL for table.');
}
return ddl.statement.flatMap((t: any) => {
if (t.type != 'statement' || t.variant != 'create' || t.format != 'table') {
return [];
}
return t.definition.flatMap((c: any) => {
if (
c.type != 'definition' ||
c.variant != 'constraint' ||
c.definition.length != 1 ||
c.definition[0].type != 'constraint' ||
c.definition[0].variant != 'foreign key'
) {
return [];
}
if (c.columns.length != 1) {
return [];
}View on GitHub (pinned to 724551b9ae)
Solutions
- Run the agent with logging to identify which table's DDL fails, then simplify that table's DDL
- Verify every introspected table has valid plain CREATE TABLE DDL in sqlite_master
- Pin the sqlite-parser version that matches your SQLite dialect and file an issue with the failing DDL
Example fix
-- before: FK syntax the parser mishandles CREATE TABLE t (a INT, FOREIGN KEY(a) REFERENCES p(x) DEFERRABLE INITIALLY DEFERRED); -- after CREATE TABLE t (a INT REFERENCES p(x));
Defensive patterns
Strategy: try-catch
Validate before calling
const bad = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND (sql IS NULL OR upper(sql) NOT LIKE 'CREATE TABLE%')").all(); if (bad.length) throw new Error('Tables with non-standard DDL: ' + bad.map(r=>r.name)); Type guard
const hasPlainCreateTable = (row: {sql: string|null}): row is {sql: string} => !!row.sql && row.sql.toUpperCase().startsWith('CREATE TABLE'); Try / catch
try { await introspectFks(table); } catch (e) { if (/non-statement or non-list/.test(String(e))) log.warn(`FK introspection failed for ${table}`); } Prevention
- Avoid exotic DDL (deferred FKs, WITHOUT ROWID quirks) in tables the agent introspects
- Test schema introspection in CI against your actual DB file
- Match sqlite-parser and SQLite versions
When it happens
Trigger: Schema introspection hitting a table whose DDL parses to an unexpected node — malformed CREATE TABLE, DDL stored as NULL, parser/SQLite version mismatch, or CREATE TABLE with inline REFERENCES clauses the parser mishandles.
Common situations: Databases with unusual DDL (WITHOUT ROWID, DEFERRABLE FKs, generated columns); sqlite-parser upgrades changing AST structure; migrating a DB dumped by a different SQLite version.
Related errors
- Encountered a non-statement or non-list when parsing DDL for
- SQLite Agent: Uncaught Exception
- User defined functions not supported in queries
- ${tableName.join('.')} is not a valid table
- `escapeTargetName` only implemented for tables and interpola
AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28).
Data as JSON: /api/errors/78b4d031502fd76d.
Report an issue: GitHub.