[Excel/Power Query] Error: Expression.Error — Token Eof Expected (unexpected end) — How to Fix It
Summary
Expression.Error: Token Eof Expected indicates that Power Query’s M parser reached the end of your code but still expected more tokens. Typical causes are unclosed parentheses or brackets, trailing commas after the last element, a missing/duplicated in statement, or stray characters after the final expression. The fastest fix is to open the Advanced Editor, scroll to the bottom, format the code (Ctrl+Shift+F), and balance delimiters. Ensure the query contains exactly one let … in FinalStep block and no text after the final expression.
Context
M code is lenient with whitespace but strict with structure. Each query generally follows the pattern:
let
Step1 = ...,
Step2 = ...,
FinalStep = ...
in
FinalStep
If any opening delimiter ((, [, {) lacks a matching close, or if a trailing comma suggests more items should follow, the parser anticipates additional tokens and throws “Eof (End of file) Expected.” This appears frequently after copy/pasting between queries, concatenating steps, or editing record/list literals by hand. The error position is often at or near the last lines, but the true cause can be a few characters earlier.
Probable Cause
- Unclosed delimiters. Missing
),], or}in nested function calls, records, or lists. - Trailing comma at the end of a block. After the last step in
let, the last record field, or the final list element. - Broken
let … instructure. Duplicatedin, missingin, or multipleletblocks spliced together incorrectly. - Stray characters after the final expression. Extra comments, quotes, or invisible characters (e.g., non-breaking spaces).
- Partial copy/paste. Code merged without closing previous constructs.
Quick Fix
- Open Advanced Editor. Home → Advanced Editor. Scroll to the bottom; most EOF issues surface in the final lines.
- Format the code. Press Ctrl+Shift+F to reindent. Misaligned or dangling delimiters become obvious.
- Balance delimiters. Count each
(,[,{and ensure matching),],}. - Remove trailing commas. The last item in a record/list or the final step in
letmust not end with a comma. - Validate
let … in. Exactly oneletand onein; theinmust reference the final step name. - Delete leftovers after the final expression. No tokens or comments after the
in FinalStepline.
// ❌ Trailing comma after FinalStep
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
Kept = Table.SelectRows(Source, each [Amount] > 0),
Final = Table.RemoveColumns(Kept, {"Notes"}),
in
Final, // <-- trailing comma causes EOF Expected
// stray text here
// ✅ Correct
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
Kept = Table.SelectRows(Source, each [Amount] > 0),
Final = Table.RemoveColumns(Kept, {"Notes"})
in
Final
Full Example
Scenario 1: Unclosed parenthesis in a function call.
// ❌ Missing closing )
Filtered = Table.SelectRows(Source, each [Qty] >= 1
// Later...
in
Filtered
→ Expression.Error: Token Eof Expected
Fix: Close the call and reformat.
Filtered = Table.SelectRows(Source, each [Qty] >= 1)
Scenario 2: Record literal missing closing bracket.
// ❌ Record not closed
Meta = [ Author = "Luis", Year = 2025
in
Meta
→ EOF Expected near end
Fix: Close with ] and ensure let … in surrounds it.
let
Meta = [ Author = "Luis", Year = 2025 ]
in
Meta
Scenario 3: Merging two queries left duplicated let/in.
// ❌ Two blocks concatenated
let
A = ...,
B = ...
in
B
let
C = Table.AddColumn(B, "Flag", each [Qty] > 0),
D = Table.RemoveColumns(C, {"Temp"})
in
D
→ EOF or unexpected tokens (duplicate let/in)
Fix: Combine into a single block.
let
A = ...,
B = ...,
C = Table.AddColumn(B, "Flag", each [Qty] > 0),
D = Table.RemoveColumns(C, {"Temp"})
in
D
Scenario 4: Trailing comma in let steps.
// ❌ Trailing comma after final step name
let
S = ...,
T = ...,
U = ...
in
U,
Fix: Remove the trailing comma.
in
U
Scenario 5: Stray characters after final expression.
// ❌ Extra characters after 'in FinalStep'
in
FinalStep ) // <-- extra ')'
Fix: Delete any tokens after the final expression.
Pitfalls & Debug
- Symptom → Error line highlights the very end. Fix → Check 1–3 lines above for a missing
),],}, or a trailing comma. - Symptom → Formatting fails or doesn’t change much. Fix → Temporarily comment out recent edits with
//; reintroduce lines incrementally. - Symptom → After pasting JSON, EOF appears. Fix → Convert to M record syntax: use
[ Key = Value ](equals) and commas between fields, not colons only. - Symptom → “near
in” message. Fix → Ensure exactly oneinand that it references an existing step identifier. - Symptom → Invisible characters at end. Fix → Backspace the last line fully, retype the
in FinalStep, and save.
Validation & Next Steps
After fixing structure, validate deterministically:
1) Ctrl+Shift+F to format; verify balanced indentation.
2) Ensure the final two lines are exactly:
in
FinalStep
3) Refresh Preview; if another syntax error appears, repeat isolate-and-fix.
Adopt a defensive routine: keep complex expressions in smaller let variables, avoid trailing commas, and prefer UI-generated steps for boilerplate. For collaboration, store a working copy of the query to diff against when EOF errors arise.
Sources
Power Query M language specification
Advanced Editor in Power Query
Power Query M function reference
Tool/Power Query, OS/Cross-platform, Topic/M Syntax & EOF Parsing