skylot/jadx · error · IOException

String read error

Error message

String read error

What it means

Thrown as an IOException by ClsSet.readString(DataInputStream, int) when the input stream returns -1 (EOF) before the expected number of string bytes are read. The method loops reading partial bytes; hitting end-of-stream mid-string indicates a truncated or corrupted .clst file.

Source

Thrown at jadx-core/src/main/java/jadx/core/clsp/ClsSet.java:472

		if (len >= 0xFF) {
			throw new JadxRuntimeException("String is too long: " + name);
		}
		writeUnsignedByte(out, bytes.length);
		out.write(bytes);
	}

	private static String readString(DataInputStream in) throws IOException {
		int len = readUnsignedByte(in);
		return readString(in, len);
	}

	private static String readString(DataInputStream in, int len) throws IOException {
		byte[] bytes = new byte[len];
		int count = in.read(bytes);
		while (count != len) {
			int res = in.read(bytes, count, len - count);
			if (res == -1) {
				throw new IOException("String read error");
			} else {
				count += res;
			}
		}
		return new String(bytes, STRING_CHARSET);
	}

	private static void writeUnsignedByte(DataOutputStream out, int value) throws IOException {
		if (value < 0 || value >= 0xFF) {
			throw new JadxRuntimeException("Unsigned byte value is too big: " + value);
		}
		out.writeByte(value);
	}

	private static int readUnsignedByte(DataInputStream in) throws IOException {
		return ((int) in.readByte()) & 0xFF;
	}

View on GitHub (pinned to e738a26571)

Solutions

  1. Delete the corrupted .clst file and regenerate or re-download it from a known-good source.
  2. Verify file integrity (checksum/size) before loading.
  3. Ensure the writing and reading jadx versions use the same STRING_CHARSET and length encoding.
Defensive patterns

Strategy: validation

Validate before calling

// Validate file integrity before loading
File clstFile = new File(path);
long expectedSize = ...; // known-good size or checksum
if (clstFile.length() < expectedSize) {
    throw new IOException("Possible truncated .clst file: " + path);
}
// Verify checksum
String checksum = DigestUtils.md5Hex(new FileInputStream(clstFile));
if (!checksum.equals(EXPECTED_CHECKSUM)) {
    throw new IOException("Checksum mismatch for .clst file");
}

Try / catch

try {
    clsSet.loadFromClstFile();
} catch (IOException e) {
    if (e.getMessage().equals("String read error")) {
        logger.error("Corrupted or truncated .clst file. Re-download or regenerate.", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Reading a .clst file that is shorter than expected — either truncated on disk, partially downloaded, or produced by an interrupted write. A version mismatch causing incorrect length decoding can also make jadx try to read past the actual data.

Common situations: Interrupted or incomplete .clst file generation. Disk corruption or partial file transfer. A version skew where readUnsignedByte decodes a length that doesn't match what was written, causing a read overrun.

Related errors


AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14). Data as JSON: /api/errors/1a14360f8b566579. Report an issue: GitHub.