cube-js/cube · error · Error
Unterminated string: ${sql}
Error message
Unterminated string: ${sql} What it means
Thrown by SqlParser.sqlUpperCase(), a pre-parse pass that uppercases SQL outside string literals while tracking quote state ('', "", ``) and comments. If the scan ends with a quote character still open, the string was never closed and the parser throws a plain Error 'Unterminated string: <sql>' with the whole SQL text.
Source
Thrown at packages/cubejs-schema-compiler/src/parser/SqlParser.ts:106
// Check for start of single-line comment
commentType = '--';
result += sql[i];
} else if (sql[i] === '/' && sql[i + 1] === '*') {
// Check for start of multi-line comment
commentType = '/*';
result += sql[i];
} else if (sql[i] === '\'' || sql[i] === '"' || sql[i] === '`') {
// Check for string literals
openChar = sql[i];
result += sql[i];
} else {
// Regular character - convert to uppercase
result += sql[i].toUpperCase();
}
}
if (openChar) {
throw new Error(`Unterminated string: ${sql}`);
}
return result;
}
protected parse() {
const { sql } = this;
const chars = new CharStream(SqlParser.sqlUpperCase(sql));
chars.getText = (start, stop) => {
if (stop >= chars.size) {
stop = chars.size - 1;
}
if (start >= chars.size) {
return '';
} else {
return sql.slice(start, stop + 1);View on GitHub (pinned to 7d981676b3)
Solutions
- Inspect the SQL in the error message and add the missing closing quote
- Validate the SQL in your database client first; only pass executable statements to the parser
- Remove quotes from comments or move them before the comment to avoid tracker confusion
- Escape embedded quotes properly (double them: 'it''s') instead of unescaped apostrophes
Example fix
// before
const p = new SqlParser("SELECT * FROM t WHERE name = 'foo");
// after
const p = new SqlParser("SELECT * FROM t WHERE name = 'foo'"); Defensive patterns
Strategy: try-catch
Validate before calling
function hasBalancedQuotes(sql) {
let open = null;
for (let i = 0; i < sql.length; i++) {
if (open) { if (sql[i] === open) open = null; }
else if (sql[i] === "'" || sql[i] === '"' || sql[i] === '`') open = sql[i];
}
return open === null;
}
if (!hasBalancedQuotes(sql)) throw new Error('SQL has an unterminated string literal'); Try / catch
try {
new SqlParser(sql); // or extractTableFrom(sql)
} catch (e) {
if (/Unterminated string/.test(e.message)) {
throw new Error('Check quotes in: ' + sql.slice(0, 120));
}
throw e;
} Prevention
- Balance every ', " and ` before passing SQL to the parser
- Escape embedded apostrophes by doubling them ('it''s')
- Avoid quote characters inside -- comments
- Preview the SQL in a database client before feeding it to scaffolding/introspection
When it happens
Trigger: Constructing a SqlParser (parse() -> sqlUpperCase) with SQL containing a quote ('...", "... or `...) that is never closed, including quotes inside comments the tracker mishandles or escaped-quote edge cases.
Common situations: Dynamically built SQL passed to scaffolding/query introspection APIs with a missing closing quote, copy-pasted SQL truncated mid-literal, or SQL where a quote appears in a -- comment causing mis-tracking.
Related errors
- SQL Parsing Error: ${this.errors.map(({ msg, column, line })
- Python Parsing Error: ${this.errors.map(({ msg, column, line
- You cannot change security context via __user from ${session
- Incorrect user name "${user}" or password
- ${queryExecution.QueryExecution?.Status?.StateChangeReason}
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/e391cc4211ff7354.
Report an issue: GitHub.