Getting 404 error when using batch operations to modify text in Google Docs via Apps Script

I’m working on a Google Apps Script project where I need to duplicate a Google Doc template and then update specific text placeholders inside it. The process works fine for creating the copies, but I run into a 404 error when trying to modify the text content.

I’m using a batch request library to handle multiple operations at once. Here’s what my code looks like:

const DATA = SpreadsheetApp.getActiveSpreadsheet()
  .getSheetByName('Sheet1')
  .getDataRange()
  .getValues()
  .filter(row => row[0] !== "")
  .map(row => [row[0], row[1]]);

function createDocuments() {
  var batchRequests = DATA.map(([id, fullName], index) => {
    return {
      method: "POST",
      endpoint: `https://www.googleapis.com/drive/v3/files/1ABC123DEF456GHI789JKL/copy`,
      requestBody: {
        parents: ["1XYZ789ABC123DEF456"], 
        name: `Contract #${id} - ${fullName}`
      }
    }
  });
  
  var result = BatchRequest.EDo({
    batchPath: "batch/drive/v3",
    requests: batchRequests,
  });
  
  console.log(result);
  updateDocumentText(result);
}

function updateDocumentText(result) {
  var documentIds = result.map((file) => {
    return file.id;
  });
  
  var updateRequests = helper.mergeArrays(DATA, documentIds).map(([contractId, clientName, docId]) => {
    return {
      method: "POST",
      endpoint: `https://docs.googleapis.com/v1/documents/${docId}:batchUpdate`,
      requestBody: {
        replaceAllText: {
          replaceText: contractId, 
          containsText: { text: "{{CONTRACT_ID}}", matchCase: true },
          replaceText: clientName, 
          containsText: { text: "{{CLIENT_NAME}}", matchCase: true }
        }
      }
    }
  });
  
  var updateResult = BatchRequest.EDo({
    batchPath: "batch/drive/v3",
    requests: updateRequests,
  });
  
  console.log(JSON.stringify(updateResult, null, 2));
}

The document creation part works perfectly and I can see the new files being created with the right names. However, when it tries to update the text content, I get a 404 error saying the URL path for batchUpdate cannot be resolved. Has anyone encountered this issue before? What might be causing this problem?

Your JSON structure is broken. You need to put the replaceAllText inside a requests array, and you can’t have two replaceText properties in the same object. Each replacement needs its own request object.

I’ve run into this automating contract generation. Here’s how it should look:

requestBody: {
  requests: [
    {
      replaceAllText: {
        containsText: { text: "{{CONTRACT_ID}}", matchCase: true },
        replaceText: contractId
      }
    },
    {
      replaceAllText: {
        containsText: { text: "{{CLIENT_NAME}}", matchCase: true },
        replaceText: clientName
      }
    }
  ]
}

The API wants an array of operations, not one messed up object. Your current syntax gets rejected before the API even looks at your content.

check your oauth scopes too. the docs api needs different permissions than drive api, so even if file creation works, text updates might fail. that 404 could also be a timing issue - new docs aren’t always ready for editing right after creation. try adding a small sleep() between operations.

You’re using the wrong batch endpoint. Your updateDocumentText function has batchPath: "batch/drive/v3" but you’re making Docs API calls, not Drive API calls. I hit this exact issue six months ago on a similar project - you need to change it to "batch/docs/v1" for document updates.

Also, your replaceAllText structure is messed up. You’ve got replaceText defined twice instead of using the proper requests array format. Wrap your text replacements in a requests array, with each replacement as a separate object containing replaceAllText with both containsText and replaceText properties.

One more thing - add a delay between creating the document and updating text. New docs sometimes aren’t ready for modifications right away.