// Apps Script

Fix "Identifier has already been declared" in Apps Script.

All .gs files in an Apps Script project share one global scope. Two files each declaring const CONFIG will collide at load time and throw "Identifier has already been declared," blocking every function. This page shows why it happens and how to fix it without rewriting everything.

I declared a constant in one .gs file, but Apps Script throws "Identifier has already been declared" and now none of my functions run.

The script

copy · paste · trigger
Config.gs
Apps Script
// Namespace all project-wide constants under one object to avoid
// global-scope collisions across .gs files.
const Config = {
  SHEET_NAME: 'Invoices',
  MAX_ROWS: 500,
  STATUS_COL: 4
};

// In any other .gs file, reference via the namespace:
// Config.SHEET_NAME, Config.MAX_ROWS, etc.
// Do NOT re-declare const Config anywhere else in the project.
function getInvoiceSheet() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  return ss.getSheetByName(Config.SHEET_NAME);
}

Need a variant? Gnaw writes a custom version from one sentence — fields, triggers, edge cases handled.

Walkthrough

Why every .gs file is the same script

Apps Script compiles all .gs files in a project into a single JavaScript execution context before running anything. There is no module system, no import/export, no file-level scope. File order in the left-hand panel affects parse order, but every top-level declaration lands in the same flat global namespace.

In the Rhino runtime (the old engine), var declarations were hoisted and silently re-assigned, so two files both writing var CONFIG = {} would race but not crash. When Google migrated projects to the V8 engine, const and let got proper block semantics, which means a second const CONFIG at the top level is a hard syntax error at parse time. The error fires before any function in the project gets a chance to run.

That last part is the frustrating detail: you may have only touched one file, but the error message points at a line you did not change. The collision is between two files, and Apps Script surfaces it as a load-time failure with no further context.

Finding the duplicate

The script editor does not cross-reference declarations across files for you. The fastest manual approach: open each .gs file in turn and search (Ctrl+F) for the exact identifier named in the error. 'Identifier has already been declared' always names the conflicting symbol, for example CONFIG or HEADERS or TAX_RATE.

The first file to declare it in parse order wins; every subsequent declaration throws. Parse order follows the file order shown in the left panel. You can drag files to change that order, but renaming the collision is a more durable fix than reordering.

If the project has more than four or five files, a faster path is to copy each file's contents into a local editor that supports multi-file search, then grep for const followed by the symbol. The first match is the keeper; every other match is the problem.

Two fixes, one rule

The clean fix is a namespace object: create one file (conventionally named Config.gs or Constants.gs) and declare a single const that holds all project-wide values as properties. const Config = { SHEET_NAME: 'Invoices', MAX_ROWS: 500 }. Every other file reads Config.SHEET_NAME. There is now only one top-level const, so V8 has nothing to complain about.

The quick fix, appropriate when a constant is only used in one function, is to move the declaration inside that function. A const declared inside a function body is scoped to that call; it never touches the global namespace. The first time I hit this error on a client project, the offending symbol was a MAX_RETRIES constant defined at the top of three separate utility files. Moving it inside the one function that actually used it took thirty seconds and required zero refactoring.

What not to do: switching from const to var to silence the error. var will suppress the crash on V8 because var re-declarations are still tolerated, but you now have two separate variables with the same name racing to initialize in an undefined order. The second write wins, which means whichever file happens to parse last sets the value, and that order is not guaranteed to be stable across deployments. You have traded a loud error for a silent, intermittent bug.

Want a custom version?

Describe your sheet and the rule you want. Gnaw writes the Apps Script — fields, triggers, edge cases — in one shot.

FAQ

4 questions
Does this error appear in all Apps Script projects or only ones that migrated to V8?
Only V8 projects. If your project was created after early 2020, it is almost certainly V8. You can verify under Project Settings: if 'Enable Chrome V8 runtime' is checked, const and let follow strict block semantics and duplicate declarations throw. Legacy Rhino projects tolerate var re-declarations silently.
I only have one .gs file and I still get this error. What else could cause it?
Libraries. Any library attached to your project contributes to the global scope under its namespace identifier, but if a library's top-level symbol matches one of yours the conflict still fires. Check Editor > Libraries and verify none of the library identifiers match your declaration. Also check HTML files: a <script> block inside an .html file does not share the .gs scope, so that is not the source, but a second .gs file created by a template wizard sometimes hides in the file list.
The error says line 1 of a file I never edit. Why?
Apps Script reports the line of the second (conflicting) declaration, not the first. If line 1 of a file you never touch declares const UTILS or const CONFIG, that file is the duplicate. The original declaration is in whichever file parsed earlier. Fix the duplicate by renaming or removing it, not by editing the file Apps Script pointed at.
Will renaming my constants to longer, unique names prevent this long-term?
It reduces the probability but does not eliminate it. On any project with more than two contributors or more than five files, name collisions come back. The namespace object pattern is the structural fix: one top-level symbol per concern, all others nested under it. That scales to twenty files without incident.