Skip to content
// Apps Script

Fix "Script function not found: doGet" in Apps Script.

When your Apps Script web app returns "Script function not found: doGet," the cause is almost always a stale deployment version, not missing code. Here is how to fix it in under five minutes.

I deployed an Apps Script web app and got "Script function not found: doGet" even though doGet is clearly in my code.

The script

copy · paste · trigger
Code.gs
Apps Script
// Minimal web app — doGet must be top-level, not inside a class or namespace

function doGet(e) {
  var page = e.parameter.page || 'home';

  if (page === 'home') {
    return HtmlService.createHtmlOutputFromFile('index')
      .setTitle('My App');
  }

  if (page === 'about') {
    return HtmlService.createHtmlOutputFromFile('about')
      .setTitle('About');
  }

  // Fallback — always return something, never return undefined
  return ContentService.createTextOutput('Not found').setMimeType(
    ContentService.MimeType.TEXT
  );
}

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

Walkthrough

Why editing your code changes nothing for deployed users

Apps Script web app deployments are versioned snapshots. When you click Deploy > New deployment (or the original Manage deployments dialog), Apps Script captures the state of your code at that moment and assigns it a version number. The public URL your users hit always resolves to that frozen version, not your current editor state.

The first time I hit this, I spent twenty minutes staring at a perfectly spelled doGet while the live URL kept returning the error. The live URL was still pointing at version 1, where doGet did not yet exist. I had never created a new deployment version after writing the function.

The fix is: Deploy > Manage deployments > edit the existing deployment > change version from the pinned number to 'New version' > click Deploy. The URL stays the same; the code it runs changes. If you want to test without touching the production URL, use the /dev endpoint (Deploy > Test deployments) — it always runs your current unsaved HEAD, no versioning involved.

The function must be named exactly doGet at the top level

Apps Script looks up the entry point by string name. That lookup is case-sensitive and scope-sensitive. A function named DoGet, doget, or doGET will not be found. Neither will a doGet that is defined inside another function, inside an object literal, or inside a class body.

The correct form is a plain top-level function declaration: function doGet(e) { ... } in any .gs file in the project. It does not have to be in Code.gs specifically, but it must be at the module's top scope. The parameter e is optional to declare but will be undefined rather than missing if you omit it, so you may as well include it.

One subtlety: if you have multiple .gs files and two of them define doGet, Apps Script will not throw a conflict error during authoring — it will silently pick one (usually the alphabetically first file). The symptom there is behavior you cannot explain. Keep one doGet per project.

Checking authorization scope when the URL is right but still fails

After you have confirmed the version is current and the function name is correct, the next most common cause is an authorization mismatch. When you deployed, Apps Script asked you to choose who can access the app (Anyone, Anyone with Google account, or Only myself) and which account it executes as (Me or User accessing the web app).

If you deployed as 'Execute as: Me' but the OAuth consent was never completed, or you later revoked permissions in your Google account security settings, requests will fail with a permissions error that can surface as the function-not-found message in some older script runtimes. Redeploy from scratch — delete the old deployment, create a new one — to force a clean authorization flow.

The /dev test URL always runs as you, the script owner, regardless of deployment settings. If /dev works but the production URL does not, authorization scope is almost certainly the difference.

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
I added doGet to my code and saved. Why does the web app URL still return the error?
Saving changes the editor state, not the deployed version. Go to Deploy > Manage deployments, edit your active deployment, set the version to 'New version,' and redeploy. The public URL will now run your updated code.
Can I test my changes without creating a new deployment every time?
Yes. Under Deploy > Test deployments you get a /dev URL that always executes your current saved code. Use that URL during development; publish a new versioned deployment only when you are ready to push to production users.
Does doGet have to be in Code.gs specifically?
No. Apps Script treats all .gs files in a project as one flat namespace. doGet can live in any .gs file as long as it is a top-level function declaration and is not duplicated across files.
My function is named doGet but I still get the error. What else could cause this?
Three things to check in order: (1) confirm the deployment version was updated after you added the function; (2) confirm doGet is not nested inside another function, object, or class; (3) check that you do not have a duplicate doGet in another .gs file, which causes silent shadowing.
// one good script a week

Get a working Apps Script snippet in your inbox, weekly.