# Syntax error: Expected end of input but got keyword > BigQuery read a complete statement and then found more text. The position is the first token that does not belong. The common causes are a second statement without a semicolon, a clause in the wrong order, and a stray keyword. Which token the message names tells you which. Source: https://docs.querylab.io/bigquery-errors/syntax-error-expected-end-of-input/ Updated: 2026-10-30 ```text Syntax error: Expected end of input but got keyword SELECT at [2:1] ``` ## What BigQuery means The parser read a whole statement, found nothing in the grammar that could continue it, and then met another token before the end of the script. `[2:1]` is line 2, column 1: the first token that does not belong. The mistake is usually just before that token, not at it. After `LIMIT 1` the parser is happy, so it cannot say anything about `LIMIT`. It only learns something is wrong when it reaches the next word. The message names the kind of token. It is the quickest way to the cause: | The message says | Look for | | ------------------------------------------------------ | ----------------------------------------------------------------------- | | `got keyword SELECT` (or another statement keyword) | a second statement with no `;` before it | | `got keyword WHERE`, `JOIN`, `GROUP`, `ORDER`, `UNION` | a clause in the wrong place. Something earlier already ended the query. | | `got identifier "c"` | a missing comma, or a misspelled keyword read as an alias | | `got "-"`, `got ")"`, `got ","`, `got "@"` | a character that cannot continue the statement | | `got string literal 'x'`, `got integer literal "2"` | two values side by side, with an operator or comma missing | ## The smallest query that reproduces it ```sql SELECT 1 SELECT 2 ``` ```text Syntax error: Expected end of input but got keyword SELECT at [2:1] ``` ## The fix **A second statement without a semicolon.** End the first one: ```sql SELECT 1 AS a; SELECT 2 AS b ``` This runs as a script of two statements. The same error appears when a statement that ends in a query, such as `CREATE TEMP TABLE x AS SELECT 1 a`, is followed by another statement with no `;`. Inside a `BEGIN ... END` block the message is different: `Syntax error: Expected ";" but got keyword SELECT at [3:1]`. **A clause after one that ends the query.** A `SELECT` has a fixed order: `FROM` (with its joins), `WHERE`, `GROUP BY`, `HAVING`, `QUALIFY`, `WINDOW`, `ORDER BY`, `LIMIT`. Once you write a later clause, an earlier one cannot come back. These all fail the same way: ```sql SELECT * FROM UNNEST([1]) AS a LIMIT 1 WHERE a = 1 ``` ```text Syntax error: Expected end of input but got keyword WHERE at [1:40] ``` | You wrote | Message names | Fix | | ---------------------------------- | --------------- | -------------------------------------------- | | `... LIMIT 1 WHERE ...` | `keyword WHERE` | `WHERE` goes before `LIMIT` | | `... ORDER BY a GROUP BY a` | `keyword GROUP` | `GROUP BY` goes before `ORDER BY` | | `... HAVING a = 1 WHERE ...` | `keyword WHERE` | `WHERE` goes before `GROUP BY` | | `... LIMIT 10 OFFSET 5 ORDER BY a` | `keyword ORDER` | `ORDER BY` goes before `LIMIT` | | `... WHERE a = 1 JOIN ...` | `keyword JOIN` | joins belong to `FROM`, before `WHERE` | | `... LIMIT 1 OFFSET 1 LIMIT 2` | `keyword LIMIT` | a query has one `LIMIT`; `OFFSET` follows it | Move the clause to where it belongs: ```sql SELECT * FROM UNNEST([1, 2]) AS a JOIN UNNEST([2]) AS b ON a = b WHERE a = 1 ``` If the clause genuinely has to run after a `LIMIT`, put the limited query in a subquery and continue outside it: ```sql SELECT * FROM (SELECT * FROM UNNEST([1, 2]) AS a ORDER BY a LIMIT 1) WHERE a = 1 ``` **A set operation after a `LIMIT`.** `LIMIT` applies to a whole `UNION ALL` chain, so the first query cannot have its own without parentheses: ```sql (SELECT a FROM UNNEST([1, 2]) AS a LIMIT 1) UNION ALL SELECT 3 ``` An `ORDER BY` and `LIMIT` at the very end apply to the combined result: `SELECT a FROM ... UNION ALL SELECT 3 ORDER BY a LIMIT 2` is valid. **A stray word.** A keyword that belongs to no clause at that point: ```sql SELECT 1 DISTINCT ``` `DISTINCT` has to follow `SELECT` directly. Likewise `CASE WHEN 1=1 THEN 2 END END` stops at the second `END`. **A missing comma.** Two names next to each other read as `a AS b`. A third name has nothing to attach to: ```sql SELECT a b c FROM (SELECT 1 a, 2 b, 3 c) ``` ```text Syntax error: Expected end of input but got identifier "c" at [1:12] ``` A missing comma before a dotted name fails at the dot instead. `SELECT a` then `t.b` on the next line reports `got "."`. **A character that does not belong.** Extra closing brackets give `got ")"`, as in `SELECT (1 + 2))` and `WITH t AS (...) SELECT * FROM t) SELECT 2`. A doubled comma gives `got ","`. A dash in an unquoted name gives `got "-"`: `SELECT 1 AS my-col`. Backtick the name, ``AS `my-col` ``, or rename it. ## The variants of the message Every line below was produced by BigQuery: ```text Syntax error: Expected end of input but got keyword SELECT at [2:1] Syntax error: Expected end of input but got keyword WHERE at [1:40] Syntax error: Expected end of input but got keyword JOIN at [1:40] Syntax error: Expected end of input but got keyword UNION at [1:40] Syntax error: Expected end of input but got keyword DISTINCT at [1:10] Syntax error: Expected end of input but got keyword AS at [1:32] Syntax error: Expected end of input but got identifier "c" at [1:12] Syntax error: Expected end of input but got string literal 'x' at [1:10] Syntax error: Expected end of input but got integer literal "2" at [1:10] Syntax error: Expected end of input but got ")" at [1:10] Syntax error: Expected end of input but got "-" at [1:15] Syntax error: Expected end of input but got "," at [1:23] Syntax error: Expected end of input but got "@" at [1:10] ``` ## Queries that look wrong but run **A trailing comma before `FROM`.** `SELECT 1 AS a, FROM UNNEST([1])` is valid. So is a trailing comma at the end of a select list with no `FROM`. **A semicolon at the end.** `SELECT 1;` is fine. A doubled `;;` is not: `Syntax error: Unexpected ";"`. **A `#standardSQL` first line.** It parses. **Two string literals side by side.** `SELECT "a" "b" AS s` returns `ab`. BigQuery joins adjacent string literals, so no error appears if you forget a comma between two quoted values. You get one value where you wanted two. ## Different errors that look like this one **`Syntax error: Unexpected keyword FROM`.** A word that cannot start or continue what the parser is reading, such as `FROM FROM` or a comma before `FROM` in a `FROM` list. See [Unexpected identifier](https://docs.querylab.io/bigquery-errors/syntax-error-unexpected-identifier/) for the same family. **`Syntax error: Unexpected end of script`.** The statement stops in the middle: `WHERE a = 1 AND` with nothing after. **`Syntax error: Expected keyword ALL or keyword DISTINCT but got keyword SELECT`.** A bare `UNION`. Write `UNION ALL` or `UNION DISTINCT`. **`Syntax error: Function call cannot be applied to this expression. Function calls require a path, e.g. a.b.c()`.** A bracket straight after a value, as in `WHERE a IN (1, 2) (3)`. **``Syntax error: WHERE not supported after FROM query; Consider using pipe operator `|> WHERE` ``.** A query that starts with `FROM` is a pipe query. See [WHERE not supported after FROM query](https://docs.querylab.io/bigquery-errors/where-not-supported-after-from-query/). **`Syntax error: Trailing comma after the WITH clause before the main query is not allowed`.** A comma after the last CTE. ## In Querylab.io Querylab.io parses in the browser as you type. These are marked as errors with BigQuery's wording, at the same token as BigQuery: a second statement without `;`, `WHERE` after `LIMIT`, `GROUP` after `ORDER BY`, `WHERE` after `HAVING`, `JOIN` after `WHERE`, `UNION` after `LIMIT`, a stray `DISTINCT`, an extra `)`, a stray string or integer literal, and a doubled `END`. For a second statement with no `;` the editor keeps checking the rest of the script. Two cases were not marked. `LIMIT 10 OFFSET 5 ORDER BY a` and `SELECT 1 AS my-col` showed no diagnostics, so only BigQuery's dry run reports them, when you pause. A doubled comma (`SELECT 1 AS a, 2 AS b,, 3`) is marked with the editor's own words, `Expected expression before comma in SELECT list`. There are quick fixes for one cause, a missing comma before a dotted name that starts the next line, as in `a` then `t.b` on the following line. The editor's lightbulb offers it from the dry-run error, and after a failed run the status bar offers it as a button. The other causes have no fix, so repair them by hand with the table above. ## Sources Based on the BigQuery documentation by Google, CC BY 4.0, rewritten with examples checked against BigQuery: - [Query syntax](https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax) - [Lexical structure and syntax](https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical) - [Procedural language, BEGIN](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language)