quarkusio/quarkus · error · IllegalArgumentException

Expected a base64 encoded byte array, got: ${text}

Error message

Expected a base64 encoded byte array, got: ${text}

What it means

DevUIRecorder.createVertxJsonMapper installs a JSON type adapter mapping vert.x Buffer to a base64-encoded string. When decoding incoming text back into a Buffer, a non-base64 string causes IllegalArgumentException, which is rethrown with 'Expected a base64 encoded byte array, got: <text>'. This means the JSON-RPC client sent something that is not valid base64 where a Buffer was expected.

Source

Thrown at extensions/devui/runtime/src/main/java/io/quarkus/devui/runtime/DevUIRecorder.java:57

@Recorder
public class DevUIRecorder {
    private static final Logger LOG = Logger.getLogger(DevUIRecorder.class);

    public void initializeJsonRpcCodec(BeanContainer beanContainer) {
        JsonRpcRouter jsonRpcRouter = beanContainer.beanInstance(JsonRpcRouter.class);
        jsonRpcRouter.initializeCodec(createVertxJsonMapper());
    }

    public static JsonMapper createVertxJsonMapper() {
        JsonMapper.Factory factory = JsonMapper.Factory.deploymentLinker().createLink(
                DevConsoleManager.getGlobal(DevJsonRpcRecorder.DEV_MANAGER_GLOBALS_JSON_MAPPER_FACTORY));
        return factory.create(new JsonTypeAdapter<>(JsonObject.class, JsonObject::getMap, JsonObject::new),
                new JsonTypeAdapter<>(JsonArray.class, JsonArray::getList, JsonArray::new),
                new JsonTypeAdapter<>(Buffer.class, buffer -> BASE64_ENCODER.encodeToString(buffer.getBytes()), text -> {
                    try {
                        return Buffer.buffer(BASE64_DECODER.decode(text));
                    } catch (IllegalArgumentException e) {
                        throw new IllegalArgumentException("Expected a base64 encoded byte array, got: " + text, e);
                    }
                }));
    }

    public void shutdownTask(ShutdownContext shutdownContext, String devUIBasePath) {
        shutdownContext.addShutdownTask(new DeleteDirectoryRunnable(devUIBasePath));
    }

    public Handler<RoutingContext> devUIWebSocketHandler() {
        return new DevUIWebSocketHandler();
    }

    public Handler<RoutingContext> uiHandler(String finalDestination,
            String path,
            List<FileSystemStaticHandler.StaticWebRootConfiguration> webRootConfigurations,
            ShutdownContext shutdownContext) {

        WebJarStaticHandler handler = new WebJarStaticHandler(finalDestination, path, webRootConfigurations);

View on GitHub (pinned to e1c734241f)

Solutions

  1. Send the payload as proper base64 (Base64.getEncoder().encodeToString(bytes))
  2. Strip any 'data:...;base64,' prefix before sending
  3. Decode/validate client-side first (e.g. atob or Buffer.from with 'base64' and strict check)

Example fix

// before
rpc.call('sendBuffer', { data: fileText });
// after
rpc.call('sendBuffer', { data: btoa(unescape(encodeURIComponent(fileText))) });
Defensive patterns

Strategy: try-catch

Validate before calling

// client side
const b64 = /^([A-Za-z0-9+/=\r\n]+)$/;
if (!b64.test(payload)) throw new Error("payload must be plain base64");

Try / catch

try { rpc.call('method', { data: payload }); }
catch (e) {
  if (String(e.message).startsWith('Expected a base64 encoded byte array')) {
    // re-encode payload as base64 and retry once
  } else { throw e; }
}

Prevention

When it happens

Trigger: A Dev UI JSON-RPC call passing a plain string, hex, or data-URI (e.g. 'data:...;base64,...') where a Buffer/base64 byte array parameter is expected; called via initializeJsonRpcCodec.

Common situations: Front-end code sending raw text or a data URL instead of stripping the prefix and base64-encoding the payload; corrupted payloads from hand-rolled JSON-RPC clients.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/808ee7166b7344ff. Report an issue: GitHub.