{"record":{"id":"af892f5596dc07ef","repo":"prestodb/presto","slug":"identifiers-must-not-start-with-a-digit-surround","errorCode":null,"errorMessage":"identifiers must not start with a digit; surround the identifier with double quotes","messagePattern":"identifiers must not start with a digit; surround the identifier with double quotes","errorType":"exception","errorClass":"ParsingException","httpStatus":null,"severity":"error","filePath":"presto-parser/src/main/java/com/facebook/presto/sql/parser/SqlParser.java","lineNumber":229,"sourceCode":"            }\n        }\n\n        @Override\n        public void exitBackQuotedIdentifier(SqlBaseParser.BackQuotedIdentifierContext context)\n        {\n            Token token = context.BACKQUOTED_IDENTIFIER().getSymbol();\n            throw new ParsingException(\n                    \"backquoted identifiers are not supported; use double quotes to quote identifiers\",\n                    null,\n                    token.getLine(),\n                    token.getCharPositionInLine());\n        }\n\n        @Override\n        public void exitDigitIdentifier(SqlBaseParser.DigitIdentifierContext context)\n        {\n            Token token = context.DIGIT_IDENTIFIER().getSymbol();\n            throw new ParsingException(\n                    \"identifiers must not start with a digit; surround the identifier with double quotes\",\n                    null,\n                    token.getLine(),\n                    token.getCharPositionInLine());\n        }\n\n        @Override\n        public void exitNonReserved(SqlBaseParser.NonReservedContext context)\n        {\n            // we can't modify the tree during rule enter/exit event handling unless we're dealing with a terminal.\n            // Otherwise, ANTLR gets confused an fires spurious notifications.\n            if (!(context.getChild(0) instanceof TerminalNode)) {\n                int rule = ((ParserRuleContext) context.getChild(0)).getRuleIndex();\n                throw new AssertionError(\"nonReserved can only contain tokens. Found nested rule: \" + ruleNames.get(rule));\n            }\n\n            // replace nonReserved words with IDENT tokens\n            context.getParent().removeLastChild();","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-parser/src/main/java/com/facebook/presto/sql/parser/SqlParser.java#L211-L247","documentation":"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.","triggerScenarios":"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.","commonSituations":"Columns auto-named after years/numbers in spreadsheets or ETL output, generated column aliases like 1x, queries against schemas with numeric-leading names.","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"],"exampleFix":"// before\nString sql = \"SELECT 2023_data FROM t\";\n// after\nString sql = \"SELECT \\\"2023_data\\\" FROM t\";","handlingStrategy":"validation","validationCode":"// Quote identifiers that start with a digit before embedding in SQL\nif (identifier.matches(\"\\\\d.*\")) {\n    identifier = '\"' + identifier.replace(\"\\\"\", \"\\\"\\\"\") + '\"';\n}","typeGuard":"boolean isDigitLeadingIdentifier(String id) {\n    return id != null && !id.isEmpty() && Character.isDigit(id.charAt(0));\n}","tryCatchPattern":"try {\n    return sqlParser.createStatement(sql);\n} catch (ParsingException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"must not start with a digit\")) {\n        throw new IdentifierQuotingRequiredException(e.getMessage(), e);\n    }\n    throw e;\n}","preventionTips":["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"],"tags":["sql","identifier","parser"],"backgroundTag":"invalid-identifier","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}