NationalSecurityAgency/ghidra · error · RegisterValueException

Invalid register value {s}. Must be hex digits only.

Error message

Invalid register value {s}. Must be hex digits only.

What it means

Thrown by RegisterValueConverter.convertValueToBigInteger when a register value stored as a String cannot be parsed as hexadecimal by new BigInteger(s, 16). String register values are expected to be hex-digit-only (with optional sign). Non-hex characters (G-Z, 'x' prefixes, spaces, decimal points) trigger this RegisterValueException.

Source

Thrown at Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/RegisterValueConverter.java:41

public class RegisterValueConverter {
	private final TraceObjectValue registerValue;
	private BigInteger value;
	private int bitLength = -1;
	private byte[] be;
	private byte[] le;

	public RegisterValueConverter(TraceObjectValue registerValue) {
		this.registerValue = registerValue;
	}

	public static BigInteger convertValueToBigInteger(Object val) throws RegisterValueException {
		if (val instanceof String s) {
			try {
				return new BigInteger(s, 16);
			}
			catch (NumberFormatException e) {
				throw new RegisterValueException(
					"Invalid register value " + s + ". Must be hex digits only.");
			}
		}
		else if (val instanceof byte[] arr) {
			// NOTE: Reg object values are always big endian
			return new BigInteger(1, arr);
		}
		else if (val instanceof Byte b) {
			return BigInteger.valueOf(b);
		}
		else if (val instanceof Short s) {
			return BigInteger.valueOf(s);
		}
		else if (val instanceof Integer i) {
			return BigInteger.valueOf(i);
		}
		else if (val instanceof Long l) {
			return BigInteger.valueOf(l);

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Normalize the stored value to bare hex digits before it reaches the converter (strip '0x', convert decimal->hex).
  2. If the value format is wrong, fix the target connector/emulator that writes register values.
  3. Catch RegisterValueException at the read site and report the offending register/value rather than crashing.

Example fix

// before
String raw = "0xFF"; // stored on the object -> parse fails

// after
String hex = raw.replaceFirst("(?i)^0x", "");
// store hex on the register object, then read via RegisterValueConverter
Defensive patterns

Strategy: try-catch

Validate before calling

if (val instanceof String s && !s.matches("(?i)[0-9a-fA-F]+")) {
    // strip '0x' / convert decimal->hex before storing
    String clean = s.replaceFirst("(?i)^0x", "");
    val = Long.toHexString(Long.parseLong(clean, 10));
}

Type guard

static boolean isHexOnly(Object val) {
    return val instanceof String s && s.matches("(?i)[0-9a-fA-F]+");
}

Try / catch

try {
    BigInteger v = new RegisterValueConverter(regVal).getValue();
} catch (RegisterValueException e) {
    // log regVal.getParent().getPath() + e.getMessage(); treat register as unreadable
}

Prevention

When it happens

Trigger: Reading a TraceObjectValue for a register whose stored String value contains non-hex characters (e.g. '0x...', 'FFh', a decimal like '256', or whitespace), then calling RegisterValueConverter.getValue().

Common situations: Loading a trace from a target/connector that writes register values as decimal or with a '0x' prefix; hand-edited trace data; version/connector changes in the value format.

Related errors


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