Encountering a 401 error message with a 'truncated server' response while using Google Apps Script

I'm currently working on a code snippet that looks like this.

  function method3()
  {
    var spreadsheetID = '1BGi80ZBoChrMXGOyCbu2pn0ptIL6uve2ib62gV-db_o';
    var sheetName = 'Form Responses 1';
    var queryColumnLetterStart = 'A';
    var queryColumnLetterEnd = 'C';
    var query = 'select * where B = "8"';

    // Omitted the last row in range selection
    var qvizURL = 'https://docs.google.com/spreadsheets/d/' + spreadsheetID + '/gviz/tq?tqx=out:json&headers=1&sheet=' + sheetName + '&range=' + queryColumnLetterStart + ":" + queryColumnLetterEnd + '&tq=' + encodeURIComponent(query);//(myQuery);
    Logger.log('qvizURL: ' + qvizURL);
  options = {muteHttpExceptions: true};

    // Fetching the data
    Logger.log(ScriptApp.getOAuthToken());
    var ret = UrlFetchApp.fetch(qvizURL, { headers: {Authorization: 'Bearer ' + ScriptApp.getOAuthToken()}}).getContentText();
    Logger.log('ret: ' + ret);

    var obj1 = JSON.parse(ret.replace("/*O_o*/", "").replace("google.visualization.Query.setResponse(", "").slice(0, -2));
    Logger.log('obj1:');
    Logger.log(obj1);
    var data = obj1.table.rows;
    Logger.log('#rows: ' + data.length);

    for(var i=0;i<data.length;i++) {
      values.push({ts:obj.table.rows[i].c[0].f, cs:obj.table.rows[i].c[1].v, or:obj.table.rows[i].c[2].v})
      Logger.log(i+': ' + values[i][ts] + ' || ' + values[i][cs] + ' || ' + values[i][or] + ' || ');
    }
  }

Logger:

18 feb. 2021 22:33:44   Informatie  qvizURL: https://docs.google.com/spreadsheets/d/1BGi80ZBoChrMXGOyCbu2pn0ptIL6uve2ib62gV-db_o/gviz/tq?tqx=out:json&headers=1&sheet=Form Responses 1&range=A:C&tq=select%20*%20where%20B%20%3D%20%228%22
18 feb. 2021 22:33:44   Informatie  ya29.A0AfH6SMBGpL2mxU7DO5p8RQfCXKP1w13wmU6aBTVZSCjfO-uj_xzkYQziMhnXATEdGREibJk9cATEGioTfQG4aGsNq7Tm05_oD0z1HKu1v4ozBF_B2XegyQ-NuXBJFmJWTX5WEpTOm0RDTlfY6uw8lK3R5HTV
18 feb. 2021 22:33:44   Fout    Exception: Request failed for https://docs.google.com returned code 401. Truncated server response: <HTML>
<HEAD>
<TITLE>Unauthorized</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<H1>Unauthorized</H1>
<H2>Error 401</H2>
</BODY>
</HTML>
 (use muteHttpExceptions option to examine full response)
    at method3(QueryTable:16:27)

I also tried adding 'muteHttpExceptions:true', but unfortunately, it only displayed truncated HTML from the fetched URL without providing any useful insights.

Do I need to authorize something for this UrlFetch function?

**** update ***

All aspects mentioned were created using one single account.

This was the original version of the manifest file (appscript.json):

{
  "timeZone": "America/New_York",
  "dependencies": {
  },
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8"}

Later, I included oauthScopes as suggested on https://developers.google.com/apps-script/concepts/scopes#viewing_scopes

{
  "timeZone": "America/New_York",
  "dependencies": {
  },
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "oauthScopes": [
      "https://www.googleapis.com/auth/spreadsheets.readonly",
      "https://www.googleapis.com/auth/userinfo.email"
  ]
}

This resulted in an error message saying: "Exception: You do not have permission to call UrlFetchApp.fetch. Required permissions: googleapis.com/auth/script.external_request".

Therefore, I added

      "https://www.googleapis.com/auth/script.external_request"

However, this caused the initial error message again: Exception: Request failed for https://docs.google.com returned code 401. Truncated server response: ...

It seems like I need to further refine the oauthScopes settings... I browsed through https://developers.google.com/workspace/add-ons/concepts/gsuite-scopes#editor_scopes, but I'm unsure about what steps to take next...

Answer №1

Your login details are invalid, please switch to Sheets Advanced Service

The 401 (Unauthorized) status code indicates that the request cannot be processed as it does not have valid authentication credentials for the intended resource.

Conversely, a server receiving valid but inadequate credentials should respond with the 403 (Forbidden) status code.

Based on your code's requirement to iterate through sheets data by retrieving the Spreadsheet range in JSON format, it is recommended to utilize the Sheets Advanced Service in Google Apps Script and make the following modifications:

Click on Services + and add Sheets API V4.

https://i.sstatic.net/s9AGf.png

Retrieve values via Sheets API in Google Apps Script and then apply filters

function SheetsAdvancedService()
{
  var spreadsheetID = 'ID';
  var sheetName = 'Form Responses 1';
  var queryColumnLetterStart = 'A';
  var queryColumnLetterEnd = 'C';

  var sheetRangeResponse = Sheets.Spreadsheets.Values.get(spreadsheetID, `${sheetName}!${queryColumnLetterStart}:${queryColumnLetterEnd}`);
  if (sheetRangeResponse.values) {
    var filteredData = sheetRangeResponse.values.filter(row => row[1] == 8) // select * where B = "8"
    Logger.log(filteredData);
    // Handle data ...
    // Or use forEach instead of filter for efficiency
  } else {
    Logger.log("No values");
  }
}

Alternatively, utilize SheetsApp for filtering purposes

function SheetsThroughGoogleAppsScript()
{
  var spreadsheetID = 'ID';
  var sheetName = 'Form Responses 1';

  var ss = SpreadsheetApp.openById(spreadsheetID);
  var sheets = ss.getSheetByName(sheetName);
  var range = sheets.getDataRange().getValues();
  if (range) {
    var filteredData = range.filter(row => row[1] == 8) // select * where B = "8"
    Logger.log(filteredData);
    // Handle data and filter columns ...
    // Or use forEach instead of filter for efficiency
  } else {
    Logger.log("No values");
  }
}

References

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for handling numerous observables in Angular 7

I am working on an Angular 7 application that deals with a total of 20 sensor data. My goal is to receive data from a selected sensor every 5 seconds using observables. For example: var sensorId = ""; // dynamically chosen from the web interface var senso ...

What is the best way to incorporate JQuery into html content retrieved through an ajax request?

In my jsp file, there is a div structured like this : <div id="response" class="response"></div> After triggering an ajax call to a servlet, the content of this div gets updated with the following elements : <div id="response" class="res ...

Exploring VueJS Router History Mode with NGinx web server

After conducting research, I discovered several issues similar to the one I am facing. Currently, I have a docker-compose setup on Digital Ocean with NGinx, VueJS, and a Static Landing Page. Everything was working fine until I added a new route with a fo ...

Control the value dynamically with Powerange using JavaScript

I have incorporated the Powerange library into my form for creating iOS style range bars. This javascript library offers a variety of options provided by the author. Is there a method to programmatically move the slider to a specific value using JavaScrip ...

I am unable to incorporate the RobotJS module into my ElectronJS project

Currently, I am working on a Windows desktop application using ElectronJS. My main challenge is integrating the RobotJS module into my project. Despite successfully downloading the module with 'npm install robotjs' and incorporating it into my ma ...

Is it recommended to utilize CDN in Vue.js for optimal performance?

Currently facing a version compatibility issue between leaflet and leaflet-draw in my vuejs project. In light of this, I am seeking alternative solutions for map function editing such as adding polylines, copy and paste functions, and more. While I did com ...

Utilizing Selenium WebDriver with Python: Harnessing Test-Created Variables in JavaScript

How can I trigger the variable a, which I set to "Text" for testing purposes? ...

Tips for sharing content within an iframe

Despite my efforts to find a solution, I have been unable to come across one that aligns with my specific situation. I currently have a form for inputting person data. Within this form, there is an iframe containing another form for adding relatives' ...

When $(.class) displays result, Javascript ceases execution

In the code snippet below, I am trying to load a group of products from a category when the user clicks on the .expandproducts button: $('.expandproducts').click(function(){ id = $(this).attr("data-id"); urlajax = document.location.origi ...

Deciding whether an altered image has been successfully loaded

Currently, I am stuck on a minor point while creating a small gallery using jQuery. The code snippet looks like this: <script type="text/javascript> $(document).ready(function(){ $('#thumb1').click(function(){ $('#fullimage ...

Controlling JavaScript Text Opacity on Scroll: Smooth Transitions from Invisible to Visible to Hidden

I am attempting to replicate the Apple Airpods page, including its animation. I have successfully implemented the animation and now I am working on rendering text while scrolling. The text appears correctly but I'm facing an issue with opacity transit ...

Encountering difficulties in sending a JavaScript array through jQuery ajax request

I'm feeling hesitant to ask this, but I can't figure out why my code isn't working. Here's what I have: <script> var formArray = new Array(); formArray['start'] = "one"; formArray['stopat'] = "two"; formArray ...

SortTable - Refresh Dropdown Filter in Header After Adding Row to Table

My tablesorter table initially displays two entries in the "License" Filter. https://i.sstatic.net/4XODb.png If I dynamically add a row, the table now looks like this: https://i.sstatic.net/vMMYc.png I have attempted to update the table using the follow ...

Error Alert: Next.js TypeScript is reporting that the necessary packages are missing from your setup

As I work on developing a basic Next.js website using their TypeScript starter, everything was going smoothly with the 'yarn dev' command. However, out of nowhere, I started encountering an error message whenever I tried to run 'yarn dev&apo ...

The functionality of .bind() is malfunctioning on both Microsoft Edge and Google Chrome browsers

Everything seems to be running smoothly on Mozilla (version 103.0), but unfortunately, it's not performing as expected on Chrome or Microsoft Edge. $('#loading').bind('ajaxStart', function () { $(this).show(); }).bind('ajaxS ...

Different ways to enhance max-http-header-size in Vue application

After being redirected from another application, I am unable to open the page and receive an error in the console: Failed to load resource: the server responded with a status of 431 (Request Header Fields Too Large). I came across information about max-h ...

What should I do to resolve the error message TypeError: _components_firebase_Firebase__WEBPACK_IMPORTED_MODULE_2__.default.auth is not a valid function?

I have implemented Firebase with next.js and organized my files as shown below. However, I am encountering an issue with using the firebase client side SDK during the sign-up process. Firebase.js is where the firebase app is initialized import firebase fr ...

What could be the reason for event.stopPropagation() not functioning properly with a switch statement

Could you please explain why the function event.stopPropagation() is not working on the switch element? Whenever I click on the switch, it prints the console log for the switch. However, when I click on the surrounding area (row), it logs the row event in ...

Issue with Bootstrap-vue pagination navigation not functioning correctly (unexpectedly refreshes upon clicking a page)

I recently updated my website's gallery pagination by following a helpful guide. However, I encountered a problem where clicking on a new page number refreshes the entire webpage, unlike the smooth transition shown in the tutorial. This is not the beh ...

ReactJS component disappearing behind the Navbar

When using my React app, I have a navigation bar at the top. The Navbar component is called in App.js, and the code snippet below shows how it is implemented. export default function App() { return ( <Router> <Fragment> ...