FlowiseAI/Flowise · error · Error
Invalid SQL statement: multiple statements are not allowed
Error message
Invalid SQL statement: multiple statements are not allowed
What it means
Thrown by assertReadOnlySqlStatement (packages/components/src/validator.ts:389) when, after stripping one optional trailing semicolon, the statement still contains ';'. This blocks stacked queries (e.g. 'SELECT 1; DROP TABLE x') which SQLite/TypeORM would otherwise execute in sequence.
Source
Thrown at packages/components/src/validator.ts:389
* All legitimate queries issued against sqlite by this chain (including langchain's own
* schema introspection, which uses `pragma_table_info()` as a table-valued function
* inside a SELECT) are single SELECT/WITH statements, so this restriction does not
* affect normal operation.
*
* @param {string} sql The SQL statement to validate
* @throws {Error} If the statement is not a single read-only SELECT/WITH statement
*/
export const assertReadOnlySqlStatement = (sql: string): void => {
if (!sql || typeof sql !== 'string') {
throw new Error('Invalid SQL statement: statement is required and must be a string')
}
let trimmed = sql.trim()
// Strip at most one trailing semicolon (+ trailing whitespace)
trimmed = trimmed.replace(/;\s*$/, '')
if (trimmed.includes(';')) {
throw new Error('Invalid SQL statement: multiple statements are not allowed')
}
if (!/^(SELECT|WITH)\b/i.test(trimmed)) {
throw new Error('Invalid SQL statement: only read-only SELECT/WITH statements are allowed')
}
if (/load_extension\s*\(/i.test(trimmed)) {
throw new Error('Invalid SQL statement: load_extension is not allowed')
}
}
/**
* Sanitize a file name to prevent path traversal attacks.
* Strips common storage prefixes, extracts the basename, runs it through
* the `sanitize-filename` package, and rejects anything that still looks unsafe.
*
* @param {string} name The file name to sanitize
*/View on GitHub (pinned to abe4a8601a)
Solutions
- Send only one SELECT/WITH statement per call.
- Strip trailing comments and the final ';' before submitting.
- Tune the chain's prompt to forbid multi-statement output.
- If you need multiple queries, run them as separate validated calls.
Example fix
// before sql = 'SELECT * FROM users; SELECT * FROM orders;' // after sql = 'SELECT * FROM users' // one statement, no trailing ';'
Defensive patterns
Strategy: validation
Validate before calling
const one = String(sql ?? '').trim().replace(/;\s*$/, '');
if (one.includes(';')) throw new Error('multi-statement SQL rejected');
assertReadOnlySqlStatement(one); Type guard
const isSingleStatement = (s: unknown): s is string => typeof s === 'string' && !s.trim().replace(/;\s*$/, '').includes(';'); Try / catch
try { assertReadOnlySqlStatement(sql) } catch (e) { if (e instanceof Error && /multiple statements/.test(e.message)) { sql = sql.split(';')[0] } else throw e } Prevention
- Send one SELECT/WITH per call.
- Strip trailing comments and the final ';' before submission.
- Prompt-tune the chain to forbid multi-statement output.
When it happens
Trigger: LLM-generated SQL contains multiple statements, e.g. 'SELECT * FROM t; SELECT * FROM u' or a trailing comment+semicolon like 'SELECT 1; -- done'. Any ';' beyond the single permitted trailing one trips it.
Common situations: LLMs trained on multi-statement scripts; copy-pasted schema-setup SQL; CTEs that incorrectly embed ';'.
Related errors
- Invalid SQL statement: only read-only SELECT/WITH statements
- Invalid SQL statement: statement is required and must be a s
- Invalid SQL statement: load_extension is not allowed
- Invalid SQLite path: path traversal attempt detected
- Invalid SQLite path: encoded path traversal attempt detected
AI-assisted analysis of FlowiseAI/Flowise@abe4a8601a (2026-08-12).
Data as JSON: /api/errors/8f986b7b535ef106.
Report an issue: GitHub.