The operation failed with an error. [400] Invalid requests[0]...
The suffix after requests[0] is the useful part. It names the operation, field or index Google rejected. The bracketed 0 means the first item in Google's request array: not a Make module number and not a spreadsheet row number.
Reduce the failing body to one request against a disposable file. Do not retry the full production batch while changing several fields at once.
1. Identify which of three endpoints you are calling
These paths look similar but accept different bodies:
| Job | Google endpoint suffix | Top-level body |
|---|---|---|
| Replace text or edit a Google Doc | /v1/documents/DOCUMENT_ID:batchUpdate | requests with Docs operations |
| Update Sheets structure, formatting or typed cells | /v4/spreadsheets/SPREADSHEET_ID:batchUpdate | requests with Sheets operations |
| Write values to Sheets ranges | /v4/spreadsheets/SPREADSHEET_ID/values:batchUpdate | valueInputOption and data |
Official references: Docs batchUpdate, Sheets batchUpdate, Sheets values.batchUpdate.
For ordinary values in A2:B2, use the values endpoint. For a cell's typed userEnteredValue or formatting, use a Sheets requests batch. For document text, use a Docs request. Bodies are not interchangeable across endpoints.
2. Check the Make module's base URL
Use Google Docs › Make an API Call for Docs. Its URL is relative to https://docs.googleapis.com/, so enter:
/v1/documents/DOCUMENT_ID:batchUpdate
Use Google Sheets › Make an API Call for Sheets. Its URL is relative to https://sheets.googleapis.com/v4/, so enter one of:
/spreadsheets/SPREADSHEET_ID:batchUpdate
/spreadsheets/SPREADSHEET_ID/values:batchUpdate
Set Method to POST and send JSON with Content-Type: application/json. The app connection supplies authorization: do not paste an unrelated bearer token. Bases and connection behavior are in the Google Docs and Google Sheets module references.
Replace the uppercase ID placeholders with real IDs from disposable files. Check the expanded input in the failed execution: a configured field can look right while its mapped value is blank or belongs to another file.
3. Prove a literal Docs text replacement
Create a disposable Doc containing NAME_SLOT. Use this body without mapped form answers:
{
"requests": [
{
"replaceAllText": {
"containsText": {
"text": "NAME_SLOT",
"matchCase": true
},
"replaceText": "Jamie Quinn"
}
}
]
}
Read the saved document after the request. It should contain the fictional name instead of the marker. NAME_SLOT is plain text on purpose: the API example does not depend on Make interpreting {{...}} template syntax.
Only replace the literal name with a mapped answer after this request works. If the literal version works and the mapped version fails, compare the final JSON bodies. An answer with a quote or a newline can break manually assembled JSON.
Use JSON › Create JSON with a data structure matching the body when building mapped requests (Make JSON reference). Valid JSON syntax still does not prove that Google's operation fields are valid.
4. Prove a Sheets values update separately
Create a disposable spreadsheet with a tab named Intake. Use the /values:batchUpdate path and this body:
{
"valueInputOption": "RAW",
"data": [
{
"range": "'Intake'!A2:B2",
"values": [["Jamie Quinn", 1234.56]]
}
]
}
The name is a JSON string and the amount is a JSON number. The range uses the tab's title. Keep data as an array and values as an array of rows. Do not wrap this body in requests, and do not put a Docs replaceAllText in it.
Inspect A2 and B2 after the call. A successful response against the wrong spreadsheet is still a failed test for your scenario.
5. Check typed cell updates and field masks
If you need Sheets updateCells, use the structural batchUpdate endpoint. This example writes two cells beginning at A2:
{
"requests": [
{
"updateCells": {
"start": {
"sheetId": 12345,
"rowIndex": 1,
"columnIndex": 0
},
"rows": [
{
"values": [
{"userEnteredValue": {"stringValue": "Jamie Quinn"}},
{"userEnteredValue": {"numberValue": 1234.56}}
]
}
],
"fields": "userEnteredValue"
}
}
]
}
12345 is an illustrative tab ID: replace it with the actual numeric sheetId. A file's spreadsheet ID is a different identifier.
The Sheets request reference specifies start or range and a field mask relative to CellData. The Sheets data types reference defines numeric numberValue and zero-based indexes. A2 is row index 1, column index 0.
Keep the test narrow. A broad range with insufficient data can clear masked fields in the remaining area. Do not use fields: "*" to hide uncertainty about which fields you intend to update.
Common errors and the correction to try
A field belongs to the other API
A Docs operation cannot run inside a Sheets requests batch. Compare the rejected operation name with the reference for the endpoint you actually called. Rebuild the smallest valid body for that endpoint.
numberValue contains formatted text
"numberValue": "€1.234,56" is a string, not a JSON number. Parse the amount according to a declared input format first. Send 1234.56 as a number only when that is the intended value. Keep currency as a separate field. For form-answer parsing, see Make invalid number: fix mapped form answers.
The tab ID is wrong
Read the spreadsheet's metadata and match the tab title to the numeric sheetId. Tab position in the UI is not the identifier. If someone recreated a tab, refresh metadata instead of reusing an old ID.
An index points outside the current Doc
For index-based document operations, retrieve the current document structure first. Prefer proving replaceAllText for simple marker replacement before adding index-based edits.
The document has several tabs
Google's document tabs guide notes that replaceAllText can affect all tabs when no tabs criteria are provided. Limit replacement when the same marker appears elsewhere.
A required revision is stale
If you send writeControl.requiredRevisionId, compare it with the current document revision. The Docs API can reject a batch with an outdated required revision. Read again; removing concurrency protection without checking content is not a repair.
The request keeps failing after Retry
Retrying unchanged malformed input does not correct its schema. Preserve the failed input, fix one cause, then test a disposable target. Do not skip the write and then treat the document as updated.
Credits per run and what a failed batch changes
At the standard non-AI rate, one executed API-call module is a one-credit planning estimate. A read followed by a write is two. Several subrequests inside one HTTP call are still one Make module execution. Check actual history. Make credits.
Docs and Sheets requests batches validate before applying. An invalid member prevents that batch's updates. This does not undo a document created or a row added by an earlier Make module: inspect those outputs before rerunning the whole scenario.
Testing steps
- Save the full error suffix and expanded failing input.
- Confirm the API, path, method and target file ID.
- Send one literal request to a disposable file.
- Read the target and check the exact changed text or cells.
- Replace one literal with one mapped answer; compare the resulting body.
- Test punctuation and the declared numeric format.
- Add remaining requests one at a time, checking output after each change.
Stop when the first newly added request fails. Do not reorder requests merely to move the reported index.
Use a simpler intake route where it fits
If your actual job is collecting form leads in Sheets and notifying Slack, start with Flowpaja's free Lead Capture → Sheets + Slack template. It is a separate intake workflow, not a patch for an arbitrary batchUpdate body.
No Make account yet? Create a free Make account (affiliate link). Flowpaja may earn a commission if you sign up through it, at no extra cost to you.