hasura/graphql-engine · error · Error
Encountered a non-statement or non-list when parsing DDL for
Error message
Encountered a non-statement or non-list when parsing DDL for table.
What it means
The SQLite agent introspects table DDL by running it through sqlite-parser. getColumnsDdl expects the parse result to be a `{type:'statement', variant:'list'}` node; anything else (unexpected parser output, empty/malformed DDL, or a parser version producing a different AST shape) throws this error during column introspection for the columnsDdl flow.
Source
Thrown at dc-agents/sqlite/src/schema.ts:185
.concat(filterForOnlyTheseTables ?? [])
.indexOf(table.name) >= 0
);
} else {
return true;
}
};
/**
* Pulls columns from the output of sqlite-parser.
* Note that this doesn't check if duplicates are present and will emit them as many times as they are present.
* This is done as an easy way to preserve order.
*
* @param ddl - The output of sqlite-parser
* @returns - List of columns as present in the output of sqlite-parser.
*/
function getColumnsDdl(ddl: any): any[] {
if (ddl.type != 'statement' || ddl.variant != 'list') {
throw new Error(
'Encountered a non-statement or non-list when parsing 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 != 'column') {
return [];
}
return [c];
});
});
}
/**
* Example:View on GitHub (pinned to 724551b9ae)
Solutions
- Inspect `SELECT name, sql FROM sqlite_master WHERE type='table'` for NULL or unusual DDL and drop/fix those tables
- Pin or upgrade the sqlite-parser dependency to match the SQLite version in use
- Clean stray internal tables (sqlite_sequence-like, shadow tables of FTS) that the agent tries to introspect
Example fix
-- before: ghost table with NULL sql CREATE VIRTUAL TABLE t USING fts5(a); -- after: exclude virtual/shadow tables or ensure introspected tables have plain CREATE TABLE DDL
Defensive patterns
Strategy: try-catch
Validate before calling
const rows = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND sql IS NOT NULL").all(); // only expose tables with parseable DDL Type guard
const hasCreateTableDdl = (row: {sql: string|null}): row is {sql: string} => typeof row.sql === 'string' && /^CREATE\s+TABLE/i.test(row.sql); Try / catch
try { await agent.getSchema(); } catch (e) { if (/non-statement or non-list/.test(String(e))) { await auditSqliteMasterDdl(); throw e; } } Prevention
- Audit sqlite_master DDL before pointing the agent at a DB
- Keep virtual/shadow tables out of the introspected set
- Pin sqlite-parser compatible with your SQLite version
When it happens
Trigger: Calling schema introspection when a table's `sqlite_master.sql` DDL is NULL (e.g. some internal/ghost tables), malformed, or uses syntax sqlite-parser can't handle (generated columns, new SQLite features, WITHOUT ROWID edge cases).
Common situations: Upgrading SQLite or the sqlite-parser dependency so AST shapes change; databases containing virtual tables, shadow tables, or views with the same name; DDL containing constructs the old parser rejects.
Related errors
- Encountered a non-statement or non-list DDL for table.
- 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/04974f1efa6dd8dc.
Report an issue: GitHub.