Debugging a web app

73 views
Skip to first unread message

Dan Hinsley

unread,
May 10, 2026, 11:05:14 AM (9 days ago) May 10
to Google Apps Script Community
I have a web app and I want to be able to step through functions like doGet in the debugger.  Is this possible?

Brett Grear

unread,
May 11, 2026, 7:49:35 AM (8 days ago) May 11
to Google Apps Script Community
It's a bit more difficult.  
I can think of 2 possible ways
- One would be to keep a separate log where it is sent to a Google Sheet (This assumes the doGet runs as you and not the person running it)
- The other way is if you have Cloud Console setup then the logs can be viewed on there.  I think you need to have setup a project and linked it to the apps script.

Sorry I haven't provided more information because I was in a rush.

Dan Hinsley

unread,
May 11, 2026, 12:06:03 PM (8 days ago) May 11
to Google Apps Script Community
I tried the sheet thing, and it works for my doGet, but not for apiSign (the function is called from a script that runs on the client side). Any idea why this would be?  I'm really having a hard time debugging this as there's no way for me to know why it's not working.

Keith Andersen

unread,
May 11, 2026, 12:28:20 PM (8 days ago) May 11
to google-apps-sc...@googlegroups.com
Have you tried suggestions from AI? 


My website: https://sites.google.com/view/klaweb/
Passions: God, Family, Scriptures, Learning, Data Management, Google Sheets + App Script and much more!



--
You received this message because you are subscribed to the Google Groups "Google Apps Script Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-apps-script-c...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/google-apps-script-community/ebd9c4f7-391f-42ed-8977-8f69e141889cn%40googlegroups.com.

Mike Castle

unread,
May 11, 2026, 2:03:52 PM (8 days ago) May 11
to google-apps-sc...@googlegroups.com
On Sun, May 10, 2026 at 8:05 AM Dan Hinsley <webs...@danhinsley.com> wrote:
> I have a web app and I want to be able to step through functions like doGet in the debugger. Is this possible?

Usually the first line of all of my handlers is something like:

Logger.log(JSON.stringify(evt, null, 2));

Then, if need be, I can write a wrapper like:

function testMe() {
const obj = {...}; // Setting values from the log
doGet(obj);
}

Then run that function under the debugger.

But, generally, handlers like doGet, doPost, addons, triggers,
google.script.run handlers, etc, should be very small. Parse and
validate the evt, then call internal functions with appropriate
arguments. If the handler is more than 5 lines of actual code, it
probably needs to be refactored to make the kind of debugging you want
to do easier.

mrc

Dan Hinsley

unread,
May 11, 2026, 2:12:10 PM (8 days ago) May 11
to Google Apps Script Community
the problem is that logger.log doesn't show up anywhere in a function that is called from a client side script

Mike Castle

unread,
May 11, 2026, 2:22:39 PM (8 days ago) May 11
to google-apps-sc...@googlegroups.com
On Mon, May 11, 2026 at 11:12 AM Dan Hinsley <webs...@danhinsley.com> wrote:
> the problem is that logger.log doesn't show up anywhere in a function that is called from a client side script

Yes it does.

Left hand panel in the UI, under `Executions`.

mrc

Peter Isakson

unread,
May 11, 2026, 3:29:19 PM (8 days ago) May 11
to Google Apps Script Community
Well, there are some cases where logger.log and I think console.log does not show the logged data in the executions view. I have seen this. Here is an explanation from Google Gemini:

In Google Apps Script, logs from doGet or doPost functions often fail to appear in the Executions list because of how web apps handle anonymous or unauthorized requests. [1, 2]
Common situations where logs do not appear include:
Web App Privacy and Authorization
  • Anonymous Access: If your web app is deployed to run as "Me" but allows access to "Anyone, even anonymous," Google may block logs from appearing in the standard Apps Script dashboard to protect user privacy.
  • Permission Issues: Logs often only show when the script owner or a user with editing rights executes the script. Requests made without an access token typically won't trigger visible execution logs. [1, 2, 3]

SMAARTE Group

unread,
May 11, 2026, 6:05:45 PM (8 days ago) May 11
to google-apps-sc...@googlegroups.com
logger.log doesn't usually work well for doget()
Here's what I use for some of my scripts.  I hope it's helpful


Ah, you're talking about the SEND_DEBUG_EMAIL flag! This is a really elegant pattern for debugging server-side Google Apps Script execution, especially for operations triggered by the frontend where viewing Logger.log output in the Apps Script dashboard can be tedious or delayed.

Here is exactly how the script captures that execution state and sends it:

1. The Buffer & Custom Logger At the very top of complex functions like processForm() and submitReply(), the script initializes an empty array to act as a transcript, alongside a custom log wrapper function:

javascript
let logBuffer = [];
const log = (msg) => {
console.log(msg); // Still logs to the cloud console
logBuffer.push(msg); // Captures the message in memory
};

2. Capturing the Execution Path Throughout the rest of the function, instead of using standard console.log() or Logger.log(), the developer uses this custom log() function to drop "breadcrumbs":

javascript
log(`New Ticket: ${ticketId}`);
// ... later ...
log(`[REJECTED] File ${fileObj.name}: ${validation.error}`);
// ... later ...
log(`CRITICAL DRIVE ERROR: ${driveErr.message}`);

3. Delivering the Transcript At the very end of the function (and crucially, also inside the catch block if a fatal error occurs), the script evaluates the flag:

javascript
if (SEND_DEBUG_EMAIL) sendDebugEmail(logBuffer.join("\n"));

4. The Email Dispatch If the flag is true, it passes the entire array—joined by line breaks into a single text block—to the sendDebugEmail() helper (located in DebugEmail.js). That helper uses GmailApp to instantly fire off an email to the ADMIN_EMAIL address with the subject Debug Log - Facility Obs and the full chronological transcript of everything that happened during that exact execution.



Regards,
Steve Horvath



--
You received this message because you are subscribed to the Google Groups "Google Apps Script Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-apps-script-c...@googlegroups.com.

Michael O'Shaughnessy

unread,
May 11, 2026, 6:42:03 PM (8 days ago) May 11
to google-apps-sc...@googlegroups.com
For what it's worth, I have usually just put console.log() all over the place!!  I use messages like "Made to the docSend function".  I then open the web app and then fire of the developer tools.  Most the time all my console.logs() will show up in the console.  At least it give me a "trace" as to where my script got to.

Kildere S Irineu

unread,
May 12, 2026, 8:18:59 AM (7 days ago) May 12
to Google Apps Script Community

O problema principal aqui é que não dá para depurar uma Web App do Apps Script como se fosse uma execução normal do editor. Funções chamadas pelo frontend, via google.script.run, rodam no servidor, mas em um contexto de execução separado. Por isso o Logger.log() pode não aparecer onde você espera, ou pode aparecer apenas em Executions no painel do Apps Script.

A melhor solução é não tentar “step through” diretamente no doGet() ou na função chamada pelo client-side. Em vez disso, separe a lógica em funções internas testáveis.

Exemplo:

function doGet(e) {
console.log('doGet event:', JSON.stringify(e));

return HtmlService
.createHtmlOutputFromFile('index')
.setTitle('My Web App');
}

function apiSign(payload) {
console.log('apiSign payload:', JSON.stringify(payload));

try {
const result = processApiSign(payload);
return {
success: true,
data: result
};
} catch (err) {
console.error('apiSign error:', err.stack || err.message);

return {
success: false,
error: err.message
};
}
}

function processApiSign(payload) {
if (!payload) {
throw new Error('Payload is required.');
}

// Sua lógica real fica aqui
return {
message: 'Processed successfully',
received: payload
};
}

function testApiSign() {
const mockPayload = {
name: 'Test User',
email: 'te...@example.com'
};

const result = apiSign(mockPayload);
console.log(JSON.stringify(result, null, 2));
}

No HTML/client-side:

<script>
google.script.run
.withSuccessHandler(function(response) {
console.log('Success:', response);

if (!response.success) {
console.error('Server error:', response.error);
}
})
.withFailureHandler(function(error) {
console.error('google.script.run failure:', error);
})
.apiSign({
name: 'Dan',
email: 'd...@example.com'
});
</script>

A correção prática é:

  1. Deixe doGet() pequeno.
  2. Coloque a lógica real em uma função separada, como processApiSign().
  3. Crie uma função testApiSign() para rodar manualmente no editor com debugger.
  4. Use console.log() e veja os detalhes em Executions.
  5. No frontend, sempre use .withFailureHandler() para capturar erros do google.script.run.

O comentário do Mike está certo: handlers como doGet, doPost e funções chamadas por google.script.run devem ser pequenos e apenas encaminhar a execução para funções internas. Isso resolve o problema de debug e melhora bastante a manutenção.

Reply all
Reply to author
Forward
0 new messages