How to Fix 'Expected Near' Syntax Errors in Roblox Luau

Last updated:

Quick answer: The 'expected near' error is a Luau syntax (parse) error: the script is compiled before it runs, so one broken construct stops everything, and the token after 'near' is where the parser choked. It is almost always a missing or misplaced end, a JavaScript-style operator like && or != that Luau does not have, or a quote or bracket that never got closed.

The Roblox error 'end' expected near 'if' — or any 'something' expected near 'something' message — is Luau telling you the script has a syntax error. Luau parses the entire script before executing a single line, so one broken construct prevents the whole script from running at all. The word before "expected" is the token the parser needed at that point, and the word after "near" is the token it actually found. In practice the cause is one of a handful of things: a missing or misplaced end, an operator Luau does not support, or a string or bracket that was never closed.

What does "expected near" actually mean?

Luau reads a script in two stages. First the parser turns the text into code it can run (compilation), then the runtime executes it. 'X' expected near 'Y' is a parse-stage error, which means the mistake is about the shape of your code, not its logic: the parser reached a token that cannot legally continue the current statement or block and gave up. Common shapes you will see in the Output window:

The parenthetical "(to close '(' at line 8)" is gold when you get it: it names the line of the opening bracket, so the mistake is somewhere between there and the reported line.

Why do I get "'end' expected" when my end is already there?

Every block opener pairs with exactly one closer, and the parser matches them strictly in order:

If your end keyword really is in the file, one of two things is happening. Either a block above it is missing its own end, so the parser hands yours to that block and then runs out at end of file — that shows up as 'end' expected near 'eof'. Or an extra end higher up closed an outer block early, and everything after it is now floating outside where it belongs.

local function giveReward(player)
	if player:GetAttribute("Level") >= 10 then
		print("reward for " .. player.Name)
	-- 'end' for the if and 'end' for the function are both missing

local function onPlayerAdded(player)
	giveReward(player)
end

The parser reports the error at or after the next thing it cannot accept — often a later local function or the end of the file — even though the real mistake is several lines up. The fix is to balance the blocks:

local function giveReward(player)
	if player:GetAttribute("Level") >= 10 then
		print("reward for " .. player.Name)
	end
end

local function onPlayerAdded(player)
	giveReward(player)
end

Two keyword traps live here. elseif continues an existing if and shares its single end, while else if opens a brand-new nested if that demands an end of its own — one missing end later, the whole file fails to parse. And a repeat ... until block that you close with end leaves the until dangling, which produces exactly the class of error this guide is about.

Which operators does Luau not have?

If you are coming from JavaScript, C, or Java, muscle memory will write operators Luau simply does not have. The parser hits the first foreign symbol and reports something like unexpected symbol near '&' or '=' expected near '|'. Here is the translation list:

Note that += itself is valid modern Luau: x += 1, x *= 2, and x ..= "!" are all compound assignments Luau adds on top of Lua. What does not exist is ++ as an increment statement, and the -- case is sneakier still: in Luau it starts a comment, so a stray count-- comments out the rest of the line and chops your statement in half.

local score = 0
local alive = true
local name = "Player"

if alive && name != "Guest" then -- wrong: && and != are not Luau
	score++
end
local score = 0
local alive = true
local name = "Player"

if alive and name ~= "Guest" then
	score += 1
end

Related: string concatenation is .., never +. "score: " .. tostring(score) is the correct way to join text and numbers — and writing that line with a stray quote in the middle (see the next section) is one of the most common ways a concatenation turns into a syntax error.

Why does my string or table break the rest of the file?

An unterminated string or bracket does not fail where you typed it — it swallows everything that follows until the parser finds a matching closer or gives up. Watch for these four:

Why is the error line number not where the mistake is?

Because the parser reports where it gave up, not where you typed the problem. It consumes tokens as long as they could still form valid code, so the reported line is the first place the story stopped making sense. Three predictable shifts:

  1. Missing end reports at end of file, or at the next keyword that cannot continue the open block.
  2. Unclosed string reports at the next matching quote character, sometimes ten lines below your typo.
  3. Extra end reports at that end itself as an unexpected token, or makes the following code fail with a different message.

The reliable method is to start at the reported line and scan upward for the nearest unclosed construct — the last function, if, for, brace, or quote that never got its closing token. The mistake sits between the last chunk that parsed cleanly and the line the error names. When the message includes "(to close '(' at line N)", start your search at line N instead.

One more property to remember: Luau reports syntax errors one at a time. Fix the first error and re-run — the next one only appears once the first is gone, so a short cascade of parse errors is normal and does not mean your script got worse.

The 30-second syntax error checklist

  1. Read the word after "near". That is where the parser choked; read the word before "expected" to see what it wanted.
  2. Check the line above the reported line and scan upward for the first unclosed block or quote.
  3. Count openers against end: every function, if, for, while, and do needs exactly one; repeat needs an until.
  4. Search the file for &&, ||, !=, ++, =>, and // — these are not Luau.
  5. Verify quotes and brackets on the reported line, especially apostrophes inside single-quoted strings.
  6. Near eof? Then an unclosed block, quote, bracket, or --[[ comment is hiding anywhere in the file — search for openers instead of staring at the bottom.
  7. Confirm then after every if condition and do after every for and while.
  8. Fix one error at a time and re-run: the parser stops at the first problem.

Common mistakes that produce 'expected near'

Learn Luau by doing

Syntax errors are the fastest errors to fix once your eye is trained, and that training only comes from writing real Luau. On Luablox you can practise in the browser through /theory, drill individual skills on /problems, and follow structured Luablox lessons that start from the very first script and build up to full gameplay systems.

Frequently asked questions

Why does Roblox say 'expected near end' when my end keyword is already there?

Because the parser matches ends to block openers strictly in order. If a function or if above yours is missing its end, the parser assigns yours to that block and complains later — or an extra end higher up closed the outer block early. Count function/if/for/while/do openers against end keywords, and remember that else if needs two ends while elseif needs one.

Is 'expected near' a compile-time or a runtime error?

Compile-time (parse-time). Luau parses the whole script before executing anything, so a syntax error means the script never starts — no code before or after the mistake runs, and no pcall in the script can catch it. Fix the syntax first; only then do runtime errors like nil values even have a chance to appear.

Why does one syntax error stop my entire Roblox script from running?

A script is compiled as one chunk, and a chunk must be completely valid before any of it executes. One broken construct invalidates the whole chunk, which is why a typo at the top can silence prints at the bottom. Luau also reports parse errors one at a time, so fix the first message and re-run to reveal the next.

What does 'near eof' mean in a Luau error message?

eof means end of file. The parser reached the last line still expecting something — usually a closing end for a block, a closing quote for a string, a closing bracket, or the end of an unterminated long comment that swallowed the rest of the file. Start counting block openers against end keywords from the top.

Can pcall catch a Luau syntax error?

No. pcall catches runtime errors while code is executing, but a syntax error is found before execution begins, so there is no running code to protect. The one exception is code you compile at runtime from a string, where a failed load reports the parse error as a return value instead — but for ordinary scripts, pcall is irrelevant to syntax errors.

Master arithmetic, relational, and logical operators in Luau to compute expressions and conditions.

Related pages