apache/superset · error · SupersetSecurityException
Custom SQL fields cannot be parsed as a single SQL statement
Error message
Custom SQL fields cannot be parsed as a single SQL statement.
What it means
SupersetSecurityException (ADHOC_SUBQUERY_NOT_ALLOWED_ERROR) raised in validate_adhoc_subquery's expression validator (models.py:1004) when a custom SQL expression cannot be parsed by sqlglot as a single statement after wrapping it as SELECT <expr>. Jinja-containing expressions are exempt (skeleton replaces Jinja blocks with NULL), so this fires only for plain SQL that fails parsing — for example unbalanced parentheses or garbage tokens in a metric/column SQL field.
Source
Thrown at superset/connectors/sqla/models.py:1004
is still inspected; structural attacks smuggled in the non-templated
portion of an otherwise-templated expression are still rejected.
Expressions whose substituted skeleton is unparseable (typically due to
``{% if %}`` control-flow templating) fall back to deferring validation
to query time, when the template processor has a real context.
"""
if not expression:
return
skeleton = _JINJA_BLOCK_RE.sub(" NULL ", expression)
contains_jinja = skeleton != expression
engine = database.backend
wrapped = f"SELECT {skeleton}"
try:
parsed = SQLStatement(wrapped, engine)
except SupersetParseError as ex:
if contains_jinja:
return
raise SupersetSecurityException(
SupersetError(
error_type=SupersetErrorType.ADHOC_SUBQUERY_NOT_ALLOWED_ERROR,
message=_(
"Custom SQL fields cannot be parsed as a single SQL statement."
),
level=ErrorLevel.ERROR,
)
) from ex
if parsed.is_set_operation():
raise SupersetSecurityException(
SupersetError(
error_type=SupersetErrorType.ADHOC_SUBQUERY_NOT_ALLOWED_ERROR,
message=_("Custom SQL fields cannot contain set operations."),
level=ErrorLevel.ERROR,
)
)
View on GitHub (pinned to f4587218dd)
Solutions
- Fix the expression so it parses as one statement: it must be an expression (not a full query), with balanced parentheses and engine-valid syntax.
- Verify the expression alone: wrap mentally in SELECT <expr> and run it against the target database.
- If the syntax is valid in your engine but sqlglot rejects it, simplify (e.g. avoid exotic operators) or file/track a sqlglot parsing issue; do not bypass the validator.
Example fix
-- before (adhoc metric SQL) SUM(CASE WHEN region = 'EMEA' THEN sales -- after SUM(CASE WHEN region = 'EMEA' THEN sales ELSE 0 END)
Defensive patterns
Strategy: validation
Validate before calling
from sqlglot import parse_one
from sqlglot.errors import ParseError
def parses_as_single_expression(expr: str) -> bool:
try:
parse_one(f"SELECT {expr}")
return True
except ParseError:
return False Try / catch
from superset.exceptions import SupersetSecurityException
try:
validate_adhoc_subquery(sql_expr, database, catalog, schema)
except SupersetSecurityException as ex:
show_user_error("Custom SQL must be a single valid SQL expression")
raise Prevention
- Validate custom SQL client-side with sqlglot parse_one(f'SELECT {expr}') before saving.
- Enter expressions, not full queries, in adhoc metric/column fields.
- Add a lint step in dataset-import tooling that parses every stored expression.
When it happens
Trigger: Entering a Custom SQL adhoc metric or column whose expression is not a valid single SQL expression (e.g. 'SUM(x' or 'SELECT * FROM t') — set operations and multi-statement input are caught by sibling checks; this one catches pure parse failures of the wrapped SELECT.
Common situations: Typos in the adhoc metric SQL box in Explore; pasting a full query instead of an expression into a metric field; dialect-specific syntax sqlglot cannot parse for the chosen database engine.
Related errors
- Custom SQL fields cannot contain set operations.
- Adhoc metric aggregate is invalid
- Adhoc metric SQL expression is invalid
- Adhoc metric expressionType is invalid
- Only `SELECT` statements are allowed
AI-assisted analysis of apache/superset@f4587218dd (2026-08-14).
Data as JSON: /api/errors/a9ab325e5f386cd0.
Report an issue: GitHub.