libgdx/libgdx · warning · IndexOutOfBoundsException

IndexOutOfBoundsException

Error message

IndexOutOfBoundsException

What it means

put(String src, int start, int end) at lines 86-91 validates its arguments BEFORE checking read-only-ness: negative start/end or (per this Harmony-derived check) start+end exceeding src.length() throws IndexOutOfBoundsException at line 88. Only after passing the bounds check does the method throw ReadOnlyBufferException at line 90. So this IndexOutOfBoundsException means the substring range you asked to write is itself invalid, independent of buffer mutability. (Note the check `start + end > src.length()` is the classic Harmony formulation; pass start=0 and end=substring length to stay inside it.)

Source

Thrown at backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/emu/java/nio/ReadOnlyCharArrayBuffer.java:88

	public CharBuffer put (char c) {
		throw new ReadOnlyBufferException();
	}

	public CharBuffer put (int index, char c) {
		throw new ReadOnlyBufferException();
	}

	public final CharBuffer put (char[] src, int off, int len) {
		throw new ReadOnlyBufferException();
	}

	public final CharBuffer put (CharBuffer src) {
		throw new ReadOnlyBufferException();
	}

	public CharBuffer put (String src, int start, int end) {
		if ((start < 0) || (end < 0) || (long)start + (long)end > src.length()) {
			throw new IndexOutOfBoundsException();
		}
		throw new ReadOnlyBufferException();
	}

	public CharBuffer slice () {
		return new ReadOnlyCharArrayBuffer(remaining(), backingArray, offset + position);
	}
}

View on GitHub (pinned to 97f4086187)

Solutions

  1. Clamp/validate the range before the call: if (start < 0 || end < 0 || start + end > src.length()) throw new IllegalArgumentException("bad range") with a descriptive message
  2. Fix the arithmetic: the end parameter here is a LENGTH paired with start, so pass put(str, 0, str.length()) for the whole string
  3. Check for -1 sentinels from index lookup (indexOf etc.) before using them as start/end

Example fix

// before
buf.put(text, offset, offset + count); // offset+count can exceed text.length()

// after
int end = Math.min(offset + count, text.length());
if (offset >= 0 && end >= 0 && offset + end <= text.length()) buf.put(text, offset, end - offset);
Defensive patterns

Strategy: validation

Validate before calling

static void checkRange(String s, int start, int end) {
  if (start < 0 || end < 0 || (long) start + (long) end > s.length())
    throw new IllegalArgumentException("range [" + start + "," + end + ") invalid for length " + s.length());
}
// call before buf.put(s, start, end)

Type guard

boolean isValidStringRange(String s, int start, int end) { return s != null && start >= 0 && end >= 0 && start + end <= s.length(); }

Try / catch

try { buf.put(str, start, end); } catch (IndexOutOfBoundsException e) { throw new IllegalArgumentException("bad substring range " + start + "/" + end + " for length " + str.length(), e); }

Prevention

When it happens

Trigger: Calling put(str, start, end) with start or end negative, or a start+end pair whose sum exceeds str.length(), on a read-only CharBuffer in the GWT emu. Example: put(text, offset, offset + count) where offset+count > text.length(), or reversed/zeroed ranges with negative values.

Common situations: Substring-copy loops ported from desktop code where the caller computed the end index against a different string than the one passed; off-by-one in offset+count arithmetic when draining a reader into a buffer; negative indices from a preceding calculation that returned -1 as an error sentinel.

Related errors


AI-assisted analysis of libgdx/libgdx@97f4086187 (2026-08-14). Data as JSON: /api/errors/2aa2a410e4f2591f. Report an issue: GitHub.