frohoff/ysoserial · error · IOException
couldn't find
Error message
couldn't find '${file}' What it means
ClassFiles.classAsBytes() loads a class's resource (the .class file, as produced by classAsFile) via the ClassLoader and throws this IOException when getResourceAsStream returns null — i.e. the class file is not on the classpath of the loader that loaded ClassFiles itself. This happens when generating ysoserial payloads for classes not present in ysoserial's classpath.
Solutions
- Add the jar/module containing the target class to ysoserial's runtime classpath (e.g. java -cp ysoserial.jar:target-lib.jar ...).
- Verify the resource exists: ClassFiles.class.getClassLoader().getResource(ClassFiles.classAsFile(clazz)) returns non-null before calling classAsBytes.
- Ensure the same ClassLoader loads both ClassFiles and the target class; avoid cross-classloader class references in shaded/isolated environments.
- If shading, keep ysoserial's original package structure so classAsFile() paths still resolve.
Example fix
// before
byte[] bytes = ClassFiles.classAsBytes(com.example.OutOfCpClass.class); // throws
// after
String res = ClassFiles.classAsFile(com.example.OutOfCpClass.class);
if (ClassFiles.class.getClassLoader().getResource(res) == null) {
throw new IllegalStateException("Add the jar containing " + res + " to the classpath");
}
byte[] bytes = ClassFiles.classAsBytes(com.example.OutOfCpClass.class); Defensive patterns
Strategy: try-catch
Validate before calling
public static void requireClassResource(Class<?> clazz) throws IOException {
String file = ClassFiles.classAsFile(clazz);
if (ClassFiles.class.getClassLoader().getResource(file) == null) {
throw new FileNotFoundException("Class resource not on classpath: " + file + " — add its jar to the runtime classpath");
}
} Type guard
public static boolean isClassOnClasspath(Class<?> clazz) {
return ClassFiles.class.getClassLoader().getResource(ClassFiles.classAsFile(clazz)) != null;
} Try / catch
try {
byte[] bytes = ClassFiles.classAsBytes(clazz);
} catch (IOException e) {
if (e.getMessage().startsWith("couldn't find")) {
throw new IllegalStateException("Target class file missing from classpath: " + e.getMessage()
+ " — add the containing jar to -cp", e);
}
throw e;
} Prevention
- Run payload generation with the target gadget/target library on the same classpath as ysoserial (-cp lib.jar:ysoserial.jar).
- Check getResource(classAsFile(clazz)) != null before calling classAsBytes for a clear pre-flight failure.
- Avoid shaded/renamed packages that break classAsFile() resource paths; verify resource presence after packaging changes.
- Be aware of classloader isolation (OSGi, app servers): ensure ClassFiles and the target class share a loader that can see the resource.
When it happens
Trigger: Calling ClassFiles.classAsBytes(SomeClass.class) where SomeClass was loaded by a parent/child loader whose resource path ('ysoserial/...' style .class path) is not resolvable by ClassFiles.class.getClassLoader(), or where the class came from generated/dynamic bytecode with no backing resource.
Common situations: Embedding ysoserial in an application and passing application classes not on the same classpath; shading/uber-jar packaging that drops or renames class resources; trying to serialize classes from a separate module/jar not on the runtime classpath; OSGi or app-server classloader isolation hiding the resource.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
AI-assisted analysis of frohoff/ysoserial@218bcffcaa (2026-09-12).
Data as JSON: /api/errors/a19e48c11547d169.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/ysoserial/payloads/util/ClassFiles.java:31
String str;
if (clazz.getEnclosingClass() == null) {
str = clazz.getName().replace(".", "/");
} else {
str = classAsFile(clazz.getEnclosingClass(), false) + "$" + clazz.getSimpleName();
}
if (suffix) {
str += ".class";
}
return str;
}
public static byte[] classAsBytes(final Class<?> clazz) {
try {
final byte[] buffer = new byte[1024];
final String file = classAsFile(clazz);
final InputStream in = ClassFiles.class.getClassLoader().getResourceAsStream(file);
if (in == null) {
throw new IOException("couldn't find '" + file + "'");
}
final ByteArrayOutputStream out = new ByteArrayOutputStream();
int len;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
return out.toByteArray();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
View on GitHub (pinned to 218bcffcaa)