shwenzhang/AndResGuard · error · AndrolibException

writeTableNameStringBlock UTF-8 length is different name

Error message

writeTableNameStringBlock UTF-8 length is different  name %d, tempByte %d

What it means

In the UTF-8 branch of writeTableNameStringBlock, the writer casts name.length() (Java UTF-16 char count) to a byte as the pool's length field and asserts the UTF-8 encoding length equals it. For non-ASCII names (multi-byte UTF-8) or names longer than 127 bytes, the lengths differ and AndrolibException is thrown.

Solutions

  1. Rename non-ASCII resource entries to ASCII-only names in the source project.
  2. Ensure AndResGuard's name obfuscation is enabled so the original (non-ASCII) names are replaced before writing.
  3. Patch the writer to encode the actual UTF-8 byte length instead of casting String.length().
  4. Identify the resource from the name field in the message and fix it in res/values.

Example fix

// before
strings[offset++] = (byte) name.length();
strings[offset++] = (byte) name.length();
// after
byte[] utf8 = name.getBytes(StandardCharsets.UTF_8);
strings[offset++] = (byte) utf8.length;
strings[offset++] = (byte) utf8.length;
Defensive patterns

Strategy: validation

Validate before calling

static boolean utf8Safe(String name) {
  return name.getBytes(StandardCharsets.UTF_8).length == name.length()
      && name.length() <= 127;
}
// ensure every resource-table name passes utf8Safe before obfuscation

Try / catch

try { ... } catch (AndrolibException e) { if (e.getMessage().contains("UTF-8 length is different")) { /* extract resource name from the log and fail with a rename hint */ } else throw e; }

Prevention

When it happens

Trigger: writeTableNameStringBlock with block.m_isUTF8 == true and a resource-table name whose UTF-8 byte length != name.length() (non-ASCII characters or length > byte range).

Common situations: Apps whose resource entries use localized/non-ASCII names, or libraries shipping resources with special characters in their names, being processed by AndResGuard.

Related errors


AI-assisted analysis of shwenzhang/AndResGuard@e4df245d82 (2026-09-12). Data as JSON: /api/errors/3891d42764bcd256. Report an issue: GitHub.

Appendix: source

Thrown at AndResGuard-core/src/main/java/com/tencent/mm/androlib/res/decoder/StringBlock.java:288

    for (i = 0; i < stringCount; i++) {
      stringOffsets[i] = offset;
      //如果找不到即没混淆这一项,直接拷贝
      if (tableProguardMap.get(i) == null) {
        //需要区分是否是最后一项
        int copyLen = (i == (stringCount - 1)) ? (block.m_strings.length - block.m_stringOffsets[i])
            : (block.m_stringOffsets[i + 1] - block.m_stringOffsets[i]);
        System.arraycopy(block.m_strings, block.m_stringOffsets[i], strings, offset, copyLen);
        offset += copyLen;
        totalSize += copyLen;
      } else {
        String name = tableProguardMap.get(i);
        if (block.m_isUTF8) {
          strings[offset++] = (byte) name.length();
          strings[offset++] = (byte) name.length();
          totalSize += 2;
          byte[] tempByte = name.getBytes(Charset.forName("UTF-8"));
          if (name.length() != tempByte.length) {
            throw new AndrolibException(String.format(
                "writeTableNameStringBlock UTF-8 length is different  name %d, tempByte %d\n",
                name.length(),
                tempByte.length
            ));
          }
          System.arraycopy(tempByte, 0, strings, offset, tempByte.length);
          offset += name.length();
          strings[offset++] = NULL;
          totalSize += name.length() + 1;
        } else {
          writeShort(strings, offset, (short) name.length());
          offset += 2;
          totalSize += 2;
          byte[] tempByte = name.getBytes(Charset.forName("UTF-16LE"));
          if ((name.length() * 2) != tempByte.length) {
            throw new AndrolibException(String.format(
                "writeTableNameStringBlock UTF-16LE length is different  name %d, tempByte %d\n",
                name.length(),

View on GitHub (pinned to e4df245d82)