NationalSecurityAgency/ghidra · error · TraceRmiError

Protocol error: Invalid value kinds

Error message

Protocol error: Invalid value kinds

What it means

Thrown by TraceRmiHandler.handleRetainValues when the RequestRetainValues.getKinds() enum value is not one of VK_ELEMENTS, VK_ATTRIBUTES, or VK_BOTH — i.e. the switch falls to default. This indicates the client sent a value-kinds enum ordinal the server does not recognize, which is a protocol/semver mismatch: a newer client is using an enum value unknown to this server.

Source

Thrown at Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/service/tracermi/TraceRmiHandler.java:1132

		}
		else {
			object.remove(lifespan);
		}
		return ReplyRemoveObject.getDefaultInstance();
	}

	protected ReplyRetainValues handleRetainValues(RequestRetainValues req) {
		// This is not a primitive DB operation, but should be more efficient server side.
		TraceObject object = requireOpenTrace(req.getOid()).getObject(req.getObject(), false);
		if (object == null) {
			return ReplyRetainValues.getDefaultInstance();
		}
		Lifespan span = toLifespan(req.getSpan());
		Collection<? extends TraceObjectValue> values = switch (req.getKinds()) {
			case VK_ELEMENTS -> object.getElements(span);
			case VK_ATTRIBUTES -> object.getAttributes(span);
			case VK_BOTH -> object.getValues(span);
			default -> throw new TraceRmiError("Protocol error: Invalid value kinds");
		};
		Set<String> keysToKeep = Set.copyOf(req.getKeysList());
		List<String> keysToDelete = values.stream()
				.map(v -> v.getEntryKey())
				.filter(k -> !keysToKeep.contains(k))
				.distinct()
				.toList();
		for (String key : keysToDelete) {
			object.setValue(span, key, null, ConflictResolution.TRUNCATE);
		}
		return ReplyRetainValues.getDefaultInstance();
	}

	protected ReplySaveTrace handleSaveTrace(RequestSaveTrace req)
			throws CancelledException, IOException {
		OpenTrace open = requireOpenTrace(req.getOid());
		try (CloseableTaskMonitor monitor = plugin.createMonitor()) {
			open.trace.save("TraceRMI", monitor);

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Align client and server to the same Ghidra/TraceRmi version.
  2. Downgrade the client feature usage to only VK_ELEMENTS/VK_ATTRIBUTES/VK_BOTH until the server is upgraded.
  3. Rebuild the client against the protobuf definitions matching the deployed server.
Defensive patterns

Strategy: type-guard

Validate before calling

RequestRetainValues.ValueKinds k = req.getKinds();
if (k != VK_ELEMENTS && k != VK_ATTRIBUTES && k != VK_BOTH) {
    throw new IllegalStateException("unsupported value kinds: " + k);
}

Type guard

boolean supportedKinds(RequestRetainValues.ValueKinds k) {
    return k == VK_ELEMENTS || k == VK_ATTRIBUTES || k == VK_BOTH;
}

Try / catch

try {
    handler.retainValues(req);
} catch (TraceRmiError e) {
    // unsupported enum -> version mismatch; align client/server versions
}

Prevention

When it happens

Trigger: Client and server are built from different protobuf schema versions where ValueKinds gained a new variant; the client serializes an unrecognized enum ordinal; a corrupted message yields an invalid enum.

Common situations: Mixing a newer TraceRmi client (or py-ghidra/ghidratrace) with an older Ghidra frontend; using an unreleased feature flag the server lacks.

Related errors


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/549dc1c116c7479d. Report an issue: GitHub.