prestodb/presto · error · ParsingException
identifiers must not start with a digit; surround the identi
Error message
identifiers must not start with a digit; surround the identifier with double quotes
What it means
Identifiers may not begin with a digit in Presto's grammar. When the lexer produces a DIGIT_IDENTIFIER token, PostProcessor.exitDigitIdentifier throws a ParsingException instructing the user to quote the identifier with double quotes.
Source
Thrown at presto-parser/src/main/java/com/facebook/presto/sql/parser/SqlParser.java:229
}
}
@Override
public void exitBackQuotedIdentifier(SqlBaseParser.BackQuotedIdentifierContext context)
{
Token token = context.BACKQUOTED_IDENTIFIER().getSymbol();
throw new ParsingException(
"backquoted identifiers are not supported; use double quotes to quote identifiers",
null,
token.getLine(),
token.getCharPositionInLine());
}
@Override
public void exitDigitIdentifier(SqlBaseParser.DigitIdentifierContext context)
{
Token token = context.DIGIT_IDENTIFIER().getSymbol();
throw new ParsingException(
"identifiers must not start with a digit; surround the identifier with double quotes",
null,
token.getLine(),
token.getCharPositionInLine());
}
@Override
public void exitNonReserved(SqlBaseParser.NonReservedContext context)
{
// we can't modify the tree during rule enter/exit event handling unless we're dealing with a terminal.
// Otherwise, ANTLR gets confused an fires spurious notifications.
if (!(context.getChild(0) instanceof TerminalNode)) {
int rule = ((ParserRuleContext) context.getChild(0)).getRuleIndex();
throw new AssertionError("nonReserved can only contain tokens. Found nested rule: " + ruleNames.get(rule));
}
// replace nonReserved words with IDENT tokens
context.getParent().removeLastChild();View on GitHub (pinned to 55bb57d202)
Solutions
- Double-quote the identifier: "1st_col"
- Rename the column/identifier so it starts with a letter or underscore
- Escape numeric-leading names at schema design time
Example fix
// before String sql = "SELECT 2023_data FROM t"; // after String sql = "SELECT \"2023_data\" FROM t";
Defensive patterns
Strategy: validation
Validate before calling
// Quote identifiers that start with a digit before embedding in SQL
if (identifier.matches("\\d.*")) {
identifier = '"' + identifier.replace("\"", "\"\"") + '"';
} Type guard
boolean isDigitLeadingIdentifier(String id) {
return id != null && !id.isEmpty() && Character.isDigit(id.charAt(0));
} Try / catch
try {
return sqlParser.createStatement(sql);
} catch (ParsingException e) {
if (e.getMessage() != null && e.getMessage().contains("must not start with a digit")) {
throw new IdentifierQuotingRequiredException(e.getMessage(), e);
}
throw e;
} Prevention
- Name columns to start with a letter or underscore at schema design time
- Auto-quote identifiers in query builders when the first char is a digit
- Sanitize spreadsheet/ETL-derived column names on ingest
- Add a schema-name lint rule banning digit-leading identifiers
When it happens
Trigger: Parsing SQL with a bare token starting with a digit used as an identifier, e.g. SELECT 1st_col FROM t or a column named 2023_data unquoted.
Common situations: Columns auto-named after years/numbers in spreadsheets or ETL output, generated column aliases like 1x, queries against schemas with numeric-leading names.
Related errors
- identifiers must not contain '${symbol}'
- mismatched input '${offendingToken}'. Expecting: ${expected}
- ${name} is too large (stack overflow while parsing)
- backquoted identifiers are not supported; use double quotes
- INVALID_TABLE_PROPERTY
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/af892f5596dc07ef.
Report an issue: GitHub.