frohoff/ysoserial · error · IllegalArgumentException

Unsupported command

Error message

Unsupported command ${command} ${parts}

What it means

Wicket1.getObject() throws this IllegalArgumentException when the command is well-formed (3 parts) but parts[0] does not match any supported operation ('copyAndDelete', 'write', 'writeOld', 'writeOldB64'). The dispatch chain falls through all branches and rethrows the original command plus the parsed parts for diagnosis.

Solutions

  1. Use one of the exact operation names: 'copyAndDelete', 'write', 'writeOld', or 'writeOldB64' (case-sensitive, no extra whitespace).
  2. Trim the command string before passing it in so leading/trailing spaces don't corrupt parts[0].
  3. If you intended base64 content on an old JRE, use 'writeOldB64'; for raw US-ASCII bytes on old JREs use 'writeOld'.

Example fix

// before
String command = "copy;/tmp/src;/tmp/dst";
// after
String command = "copyAndDelete;/tmp/src;/tmp/dst";
Defensive patterns

Strategy: validation

Validate before calling

private static final Set<String> WICKET1_OPS = new HashSet<>(Arrays.asList("copyAndDelete", "write", "writeOld", "writeOldB64"));
public static void validateWicket1Op(String command) {
    String op = command.split(";", -1)[0].trim();
    if (!WICKET1_OPS.contains(op)) {
        throw new IllegalArgumentException("Unsupported Wicket1 op '" + op + "'; use copyAndDelete|write|writeOld|writeOldB64");
    }
}

Type guard

public static boolean isSupportedWicket1Op(String command) {
    if (command == null) return false;
    String op = command.split(";", -1)[0].trim();
    return op.equals("copyAndDelete") || op.equals("write") || op.equals("writeOld") || op.equals("writeOldB64");
}

Try / catch

try {
    DiskFileItem item = new Wicket1().getObject(command);
} catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("Unsupported command")) {
        System.err.println("Op must be exactly one of: copyAndDelete, write, writeOld, writeOldB64 (case-sensitive)");
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling getObject("<unknownOp>;<a>;<b>") where <unknownOp> is anything other than copyAndDelete, write, writeOld, or writeOldB64 — e.g. 'copy;src;dst', 'Write;...', or a misspelled 'writeOldb64'.

Common situations: Case-sensitivity mistakes ('Write' instead of 'write'), using operation names from other ysoserial payloads, misspelling the base64 variant ('writeoldb64' vs 'writeOldB64'), or trailing whitespace making 'write ' !== 'write'.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of frohoff/ysoserial@218bcffcaa (2026-09-12). Data as JSON: /api/errors/32786aca2e141363. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/ysoserial/payloads/Wicket1.java:77

        	throw new IllegalArgumentException("Bad command format.");
        }

        if ("copyAndDelete".equals(parts[0])) {
            return copyAndDelete(parts[1], parts[2]);
        }
        else if ("write".equals(parts[0])) {
            return write(parts[1], parts[2].getBytes("US-ASCII"));
        }
        else if ("writeB64".equals(parts[0]) ) {
            return write(parts[1], Base64.decodeBase64(parts[2]));
        }
        else if ("writeOld".equals(parts[0]) ) {
            return writeOldJRE(parts[1], parts[2].getBytes("US-ASCII"));
        }
        else if ("writeOldB64".equals(parts[0]) ) {
            return writeOldJRE(parts[1], Base64.decodeBase64(parts[2]));
        }
        throw new IllegalArgumentException("Unsupported command " + command + " " + Arrays.toString(parts));
    }

	public void release(DiskFileItem obj) throws Exception {
	}

    private static DiskFileItem copyAndDelete ( String copyAndDelete, String copyTo ) throws IOException, Exception {
        return makePayload(0, copyTo, copyAndDelete, new byte[1]);
    }

    // writes data to a random filename (update_<per JVM random UUID>_<COUNTER>.tmp)
    private static DiskFileItem write ( String dir, byte[] data ) throws IOException, Exception {
        return makePayload(data.length + 1, dir, dir + "/whatever", data);
    }

    // writes data to an arbitrary file
    private static DiskFileItem writeOldJRE(String file, byte[] data) throws IOException, Exception {
        return makePayload(data.length + 1, file + "\0", file, data);
    }

View on GitHub (pinned to 218bcffcaa)