Tencent/matrix · error · IllegalArgumentException
obj is not closeable
Error message
obj ${obj} is not closeable What it means
IOUtil.closeQuietly closes Closeable, ZipFile, and similar known closeable types while swallowing exceptions; if the object is none of the recognized types it throws IllegalArgumentException 'obj X is not closeable'. It's a programming-error guard: you passed something the utility doesn't know how to close.
Solutions
- Make the resource implement java.io.Closeable (or AutoCloseable and handle it) before passing to closeQuietly.
- Close it directly with try-with-resources instead of IOUtil.
- Add an instanceof branch in a local helper for the specific type (e.g. Channel) that IOUtil doesn't cover.
- Check for null first — a wrong variable being passed is the usual root cause.
Example fix
// before
IOUtil.closeQuietly(someChannel); // IllegalArgumentException
// after
if (someChannel instanceof Closeable) {
IOUtil.closeQuietly(someChannel);
} else if (someChannel != null) {
try { someChannel.close(); } catch (Throwable ignored) { }
} Defensive patterns
Strategy: type-guard
Validate before calling
if (obj instanceof Closeable || obj instanceof ZipFile) {
IOUtil.closeQuietly(obj);
} Type guard
static boolean isCloseable(Object obj) {
return obj instanceof Closeable || obj instanceof ZipFile;
} Try / catch
try {
IOUtil.closeQuietly(resource);
} catch (IllegalArgumentException e) {
Log.w(TAG, "resource not closeable by IOUtil: " + resource.getClass());
} Prevention
- Ensure resources implement java.io.Closeable before handing them to IOUtil.
- Prefer try-with-resources for anything AutoCloseable that IOUtil doesn't recognize.
- Check the variable you pass — wrong-variable bugs surface here.
- Extend with a local helper for special types (e.g. Channels) instead of forcing IOUtil.
When it happens
Trigger: Passing an object that is neither Closeable nor ZipFile (e.g. a raw Channel type on an old API level, a custom resource, or null wrapper types) to IOUtil.closeQuietly.
Common situations: Refactoring a stream to a new resource class that doesn't implement Closeable; calling closeQuietly with AutoCloseable implementations that predate Closeable; misuse in tests with mocks that don't implement the interface.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Illegal clazz type
- Both of invoker and fieldName can not be null or nil.
- TaskInitException wrapping e.getMessage()…
- RAF err
- ProcStatReader error
AI-assisted analysis of Tencent/matrix@3b8293bd65 (2026-09-08).
Data as JSON: /api/errors/b970f0acceb61106.
Report an issue: GitHub.
Appendix: source
Thrown at matrix/matrix-android/matrix-commons/src/main/java/com/tencent/matrix/javalib/util/IOUtil.java:143
try {
((Closeable) obj).close();
} catch (Throwable ignored) {
// ignore
}
} else if (obj instanceof AutoCloseable) {
try {
((AutoCloseable) obj).close();
} catch (Throwable ignored) {
// ignore
}
} else if (obj instanceof ZipFile) {
try {
((ZipFile) obj).close();
} catch (Throwable ignored) {
// ignore
}
} else {
throw new IllegalArgumentException("obj " + obj + " is not closeable");
}
}
private IOUtil() {
throw new UnsupportedOperationException();
}
}
View on GitHub (pinned to 3b8293bd65)