HMCL-dev/HMCL · error · IllegalArgumentException
Theme-pack asset entry is empty
Error message
Theme-pack asset entry is empty
What it means
normalizeEntryName validates theme-pack ZIP entry names before use. After trimming and normalizing backslashes to slashes, an empty name throws IllegalArgumentException("Theme-pack asset entry is empty"). The name is used for path-safe asset lookup, so emptiness is rejected first.
Solutions
- Provide a non-empty asset entry name starting with assets/
- Check the source data (ZIP manifest, config) for blank entry names before constructing ThemePackAsset
- Ensure the variable supplying the entry name is actually initialized
Example fix
// before
String name = cfg.get("icon"); // ""
ThemePackAsset.of(name);
// after
String name = cfg.get("icon");
if (name != null && !name.isBlank()) ThemePackAsset.of(name); Defensive patterns
Strategy: validation
Validate before calling
static boolean isUsableEntryName(String name) {
return name != null && !name.trim().isEmpty();
} Type guard
static boolean isNonEmpty(String s) {
return s != null && !s.isBlank();
} Try / catch
try {
ThemePackAsset.of(entryName);
} catch (IllegalArgumentException e) {
log.warn("Ignoring bad asset entry: " + e.getMessage());
} Prevention
- Never pass null/blank entry names; check before constructing assets
- Validate pack manifests for blank entry keys
- Initialize the variable supplying the entry name
When it happens
Trigger: Passing "" or a whitespace-only string (e.g. " ") to ThemePackAsset construction / normalizeEntryName.
Common situations: Reading a ZIP manifest or config where an entry key was left blank, or programmatically building asset names with an unset variable.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Theme-pack asset entry must be relative:
- Theme-pack asset entry must be under assets/:
- Theme-pack asset entry must be a file:
- Theme-pack asset entry contains a control character:
- Theme-pack author must be an object or a string
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/6a82ee2a1b477cb7.
Report an issue: GitHub.
Appendix: source
Thrown at HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemePackAsset.java:62
///
/// @param source the resource to copy
/// @param entryName the normalized zip entry name under `assets/`
public ThemePackAsset {
Objects.requireNonNull(source);
entryName = normalizeEntryName(entryName);
}
/// Normalizes and validates a zip entry name.
///
/// @param entryName the entry name to validate
/// @return the normalized entry name
/// @throws IllegalArgumentException if the entry name is unsafe or outside `assets/`
static String normalizeEntryName(String entryName) {
Objects.requireNonNull(entryName);
String normalized = entryName.trim().replace('\\', '/');
if (normalized.isEmpty()) {
throw new IllegalArgumentException("Theme-pack asset entry is empty");
}
if (normalized.startsWith("/") || normalized.matches("^[A-Za-z]:.*")) {
throw new IllegalArgumentException("Theme-pack asset entry must be relative: " + entryName);
}
if (!normalized.startsWith(ASSETS_PREFIX)) {
throw new IllegalArgumentException("Theme-pack asset entry must be under assets/: " + entryName);
}
if (normalized.endsWith("/")) {
throw new IllegalArgumentException("Theme-pack asset entry must be a file: " + entryName);
}
for (String segment : normalized.split("/")) {
if (segment.isEmpty() || ".".equals(segment) || "..".equals(segment)) {
throw new IllegalArgumentException("Theme-pack asset entry contains an unsafe segment: " + entryName);
}
for (int i = 0; i < segment.length(); i++) {
char ch = segment.charAt(i);
if (Character.isISOControl(ch) || ch == '\0') {View on GitHub (pinned to 24702dc5a0)