0
votes

I'm stumped by a 400-status when using the Google Docs API to write certain Unicode characters to a Google Doc:

HttpError: https://docs.googleapis.com/v1/documents/xxxxxxxxx:batchUpdate?alt=json returned "Invalid requests[0].insertText: The insertion index cannot be within a grapheme cluster.">

I've managed to boil this down to its smallest example. The routine below attempts to insert (in order):

  • The string of Thai characters 'ถ้ามีลูกแล้วไม่ส่งเรียนพิเศษอะไรเลย จะเป็นอะไรไหมครับ'
  • A newline, above/before the string above

Code:

from google.oauth2.service_account import Credentials
from googleapiclient.discovery import build

SCOPES = [
    "https://www.googleapis.com/auth/documents",
    "https://www.googleapis.com/auth/drive",
    "https://www.googleapis.com/auth/drive.file",
    "https://www.googleapis.com/auth/drive.appdata",
    "https://www.googleapis.com/auth/drive.metadata",
]

credentials = Credentials.from_service_account_file("data/gdocscredentials.json", scopes=SCOPES)
svc = build("docs", "v1", credentials=credentials).documents()

requests = [ 
    {
        "insertText": {
            "location": {
                #  The zero-based index, in UTF-16 code units
                "index": 1
            }, 
            "text": "ถ้ามีลูกแล้วไม่ส่งเรียนพิเศษอะไรเลย จะเป็นอะไรไหมครับ"
        }
    },
    {"insertText": {"location": {"index": 1}, "text": "\n"}}

]
svc.batchUpdate(
    documentId="xxxxxxxxx",
    body={"requests": requests}
).execute()

So, the error alludes to the Thai string containing (or being) a grapheme cluster. The docs refer to this:

The API may implicitly adjust the location to prevent insertions within Unicode grapheme clusters. When this happens, the text is inserted immediately after the grapheme cluster.

How do I properly correct this error?

Google mentions that indexes are measured in UTF-16 code units. But that doesn't seem like it should matter here since this code snippet is using the 'work backwards' approach that is itself recommended by the same documentation page.

1

1 Answers

2
votes

How about this answer?

Issue and solution:

The characters of ถ้ามีลูกแล้วไม่ส่งเรียนพิเศษอะไรเลย จะเป็นอะไรไหมครับ are 2 bytes. I think that the reason of your issue is due to this. When a text is try to be put to the center of a 2-byte character, such error occurs.

From your request body, I thought that you want to put ถ้ามีลูกแล้วไม่ส่งเรียนพิเศษอะไรเลย จะเป็นอะไรไหมครับ to the index 1 and then, you want to put the line break \n to the index 1. In this case, \nถ้ามีลูกแล้วไม่ส่งเรียนพิเศษอะไรเลย จะเป็นอะไรไหมครับ is the same situation.

Sample situation 1:

When the text is put to new Google Document, the following request body can be used.

requests = [
    {"insertText": {"location": {"index": 1}, "text": "\nถ้ามีลูกแล้วไม่ส่งเรียนพิเศษอะไรเลย จะเป็นอะไรไหมครับ"}}
]
  • When your current request body is used for the new Google Document, an error occurs at {"insertText": {"location": {"index": 1}, "text": "\n"}}. Because \n with "index": 1 cannot be put to the 2 byte character.

Sample situation 2:

When the text is put to the Google Document including the texts of the Thai characters, the following request body can be used.

requests = [
    {"insertText": {"location": {"index": 2}, "text": "\nถ้ามีลูกแล้วไม่ส่งเรียนพิเศษอะไรเลย จะเป็นอะไรไหมครับ"}}
]
  • "index": 2 is used for the existing 2 byte characters.
  • In this case, if the text of ถ้ามีลูกแล้วไม่ส่งเรียนพิเศษอะไรเลย จะเป็นอะไรไหมครับ has already been existing to the first paragraph, the additional text of \nถ้ามีลูกแล้วไม่ส่งเรียนพิเศษอะไรเลย จะเป็นอะไรไหมครับ splits the existing texts like ถ\nถ้ามีลูกแล้วไม่ส่งเรียนพิเศษอะไรเลย จะเป็นอะไรไหมครับ้ามีลูกแล้วไม่ส่งเรียนพิเศษอะไรเลย จะเป็นอะไรไหมครับ. By this, 2 byte character cannot be put to the 1st index to Document with existing 2 byte character. Unfortunately, in the current stage, I think that this is due to the issue of Google side.
  • If the text of sample, which is 1 byte character, has already been existing to the first paragraph, the additional text of \nถ้ามีลูกแล้วไม่ส่งเรียนพิเศษอะไรเลย จะเป็นอะไรไหมครับ is put like \nถ้ามีลูกแล้วไม่ส่งเรียนพิเศษอะไรเลย จะเป็นอะไรไหมครับsample.

Reference:

If I misunderstood your question and this was not the direction you want, I apologize.