iBotPeaches/Apktool · error · IndexOutOfBoundsException

Attribute index out of range: index=%s, length=%s

Error message

Attribute index out of range: index=%s, length=%s

What it means

getAttribute(int) throws IndexOutOfBoundsException when attribute lookup happens off a START_TAG event, when the parser has no attributes array, or when the requested index is negative / >= attribute count. The formatted message includes the offending index and actual length.

Source

Thrown at brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/BinaryXmlResourceParser.java:585

    public int nextTag() throws XmlPullParserException, IOException {
        int eventType = next();
        if (eventType == TEXT && isWhitespace()) {
            eventType = next();
        }
        if (eventType != START_TAG && eventType != END_TAG) {
            throw new XmlPullParserException("Expected start or end tag.", this, null);
        }
        return eventType;
    }

    // Utility methods

    private Attribute getAttribute(int index) {
        if (mEventType != START_TAG) {
            throw new IndexOutOfBoundsException("Parser must be on START_TAG to get attributes.");
        }
        if (mAttributes == null || index < 0 || index >= mAttributes.length) {
            throw new IndexOutOfBoundsException(
                String.format("Attribute index out of range: index=%s, length=%s",
                    index, mAttributes != null ? mAttributes.length : 0));
        }
        return mAttributes[index];
    }

    private ResId getAttributeNameResourceId(int index) {
        if (mResourceMap == null) {
            return ResId.NULL;
        }
        Attribute attr = getAttribute(index);
        if (attr == null || attr.name < 0 || attr.name >= mResourceMap.length) {
            return ResId.NULL;
        }
        return mResourceMap[attr.name];
    }

    private void reset() {

View on GitHub (pinned to 79b63384d7)

Solutions

  1. Always iterate with `for (int i = 0; i < parser.getAttributeCount(); i++)` instead of hardcoded indexes.
  2. Prefer name-based lookup getAttributeValue(namespace, name) which is order-independent.
  3. Ensure the parser is on START_TAG (check getEventType()) before attribute access.
  4. Log getAttributeCount() for the failing element to see the real length.

Example fix

// before
String value = parser.getAttributeValue(2); // may not exist

// after
String value = parser.getAttributeValue("http://schemas.android.com/apk/res/android", "name");
// or iterate:
for (int i = 0; i < parser.getAttributeCount(); i++) {
    System.out.println(parser.getAttributeName(i) + "=" + parser.getAttributeValue(i));
}
Defensive patterns

Strategy: validation

Validate before calling

if (parser.getEventType() != XmlPullParser.START_TAG) throw new IllegalStateException("attributes need START_TAG");
int n = parser.getAttributeCount();
for (int i = 0; i < n; i++) { /* use i, never a hardcoded index */ }

Try / catch

String v = index < parser.getAttributeCount() ? parser.getAttributeValue(index) : null;
if (v == null) v = parser.getAttributeValue(namespace, name); // name-based fallback

Prevention

When it happens

Trigger: Calling getAttributeValue(index)/getAttributeName(index) outside START_TAG, or with a hardcoded index larger than this element's attribute count (binary XML attributes vary per element; indexes are not stable across tags).

Common situations: Copying attribute-index code between elements assuming fixed ordering; iterating attributes of one tag while the parser advanced to the next; AXML where some elements legitimately have fewer attributes.

Related errors


AI-assisted analysis of iBotPeaches/Apktool@79b63384d7 (2026-08-14). Data as JSON: /api/errors/ace20d5a597f5416. Report an issue: GitHub.