Quick answer
You tried to reassign a variable declared with const. const locks the binding (the name) to its initial value permanently — it does not lock the value's contents. If you need to change what the variable points to, declare it with let instead; if you only need to change an object's property or push to an array, that's mutation, which const already allows.
The exact error string
const count = 0;
count = count + 1;
// Uncaught TypeError: Assignment to constant variable.
const total = 0;
total += 10;
// Uncaught TypeError: Assignment to constant variable.
Reassignment vs mutation
This is the single most important distinction for this error: const forbids pointing the variable at a new value (reassignment) but says nothing about changing an object or array's existing contents (mutation).
const arr = [1, 2, 3];
arr.push(4); // ✅ mutation — arr still points to the same array
arr[0] = 99; // ✅ mutation — same array, different contents
arr = [5, 6]; // ❌ reassignment — Assignment to constant variable
const user = { name: "Ada" };
user.name = "Grace"; // ✅ mutation — same object, updated property
user = { name: "X" }; // ❌ reassignment
Cause 1: a loop counter declared const
for (const i = 0; i < 10; i++) {
// ❌ i++ reassigns i on the first iteration
}
for (let i = 0; i < 10; i++) {
// ✅ i needs to change each iteration — use let
}
Cause 2: a running total or accumulator
const total = 0;
for (const price of prices) {
total += price; // ❌ total needs to be reassigned each pass
}
let total = 0; // ✅
for (const price of prices) {
total += price; // fine — `price` itself stays const per iteration
}
Cause 3: a flag that toggles
const isOpen = false;
function toggle() {
isOpen = !isOpen; // ❌ reassignment
}
let isOpen = false; // ✅ this value is meant to change over time
function toggle() {
isOpen = !isOpen;
}
Cause 4: destructured bindings are const too
const { page } = query;
page = page + 1; // ❌ `page` is its own const binding, regardless of `query`
let { page } = query; // ✅ if you intend to reassign it
page = page + 1;
Common variants at a glance
| Pattern | Why it's reassignment | Fix |
|---|---|---|
const i = 0; i++ | increment rebinds i | declare the counter with let |
const total = 0; total += x | += is shorthand for reassignment | use let total |
const flag = false; flag = true | direct reassignment | use let flag |
arr.push(x) on a const arr | not an error — mutation is allowed | no fix needed |
obj.key = x on a const obj | not an error — mutation is allowed | no fix needed |
Debugging checklist
- ✓ Read the failing line — is it
=/+=/++on the variable itself (reassignment)? - ✓ If yes, and the value genuinely needs to change: switch the declaration to
let - ✓ If you only meant to update a property or array element: that's mutation, already allowed with
const— check you didn't accidentally reassign the whole variable instead - ✓ Loop counters and accumulators almost always need
let, notconst - ✓ Destructured variables are independent bindings — use
let { x } = objifxwill be reassigned
Frequently Asked Questions
What does 'Assignment to constant variable' mean?
You used = (or +=, -=, ++, etc.) on a variable declared with const, which only allows a single assignment at declaration. Any later attempt to rebind that name to a new value throws this TypeError, whether the new value is the same type or not.
Can I change the contents of a const object or array?
Yes. const only locks the binding (the variable name), not the value's contents. const arr = [1,2]; arr.push(3) works fine — you're mutating the array, not reassigning arr. Only arr = [4,5] (pointing the name at a different array) throws.
Why does my for loop throw this?
for (const i = 0; i < 10; i++) declares i as const, and the loop's own i++ step tries to reassign it on the very first iteration. Loop counters that increment need let, not const — reserve const for the loop body's per-iteration values that don't change.
Why does a counter or accumulator variable throw this?
Any variable you plan to reassign — a running total, a counter, a flag that flips — must be declared with let. const communicates "this binding will never change"; if your code changes it, that's a signal the declaration should be let, not a bug to work around.
Does destructuring into a const also lock the fields?
const { a, b } = obj creates two new const bindings, a and b — reassigning either later throws the same error, even though obj itself might be mutable. The rule is per-binding, not inherited from where the value came from.
How do I fix this quickly?
If the variable's value genuinely needs to change over time, change its declaration from const to let. If you only meant to update a property or push to an array (not rebind the variable itself), use the mutating operation instead of assignment — the const declaration is already correct.
More JavaScript & runtime errors
Browse the full reference for JavaScript, Node.js, and database errors — exact message, cause, and fix.