{"record":{"id":"b58a6942c8f15023","repo":"NationalSecurityAgency/ghidra","slug":"cannot-convert","errorCode":null,"errorMessage":"Cannot convert ","messagePattern":"Cannot convert ","errorType":"exception","errorClass":"ClassCastException","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceObjectRegister.java","lineNumber":89,"sourceCode":"\t}\n\n\t@Override\n\tpublic byte[] getValue(long snap) {\n\t\tTraceObjectValue ov = object.getValue(snap, TraceRegister.KEY_VALUE);\n\t\tif (ov == null) {\n\t\t\treturn null;\n\t\t}\n\t\tObject val = ov.getValue();\n\t\tif (val instanceof byte[] arr) {\n\t\t\t// TODO: Should I correct mismatched size?\n\t\t\treturn arr;\n\t\t}\n\t\tif (val instanceof String str) {\n\t\t\t// Always base 16. Model API says byte array for register value is big endian.\n\t\t\tBigInteger bigVal = new BigInteger(str, 16);\n\t\t\treturn Utils.bigIntegerToBytes(bigVal, getByteLength(snap), true);\n\t\t}\n\t\tthrow new ClassCastException(\"Cannot convert \" + val + \" to byte array for register value\");\n\t}\n\n\t@Override\n\tpublic void setState(Lifespan lifespan, TraceMemoryState state) {\n\t\t// NB. There's no model equivalent, so encode using ordinal\n\t\tobject.setValue(lifespan, KEY_STATE, state.ordinal());\n\t}\n\n\t@Override\n\tpublic TraceMemoryState getState(long snap) {\n\t\treturn TraceMemoryState.values()[TraceObjectInterfaceUtils.getValue(object, snap, KEY_STATE,\n\t\t\tInteger.class, TraceMemoryState.UNKNOWN.ordinal())];\n\t}\n\n\t@Override\n\tpublic TraceChangeRecord<?, ?> translateEvent(TraceChangeRecord<?, ?> rec) {\n\t\t// TODO: Once we decide how to map registers....\n\t\treturn null;","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceObjectRegister.java#L71-L107","documentation":"Thrown by DBTraceObjectRegister.getValue() when the stored register value is neither a byte[] nor a String, and thus cannot be converted to a byte array. The method checks for byte[] (returned directly) and String (parsed as hex via BigInteger). Any other type triggers a ClassCastException (unchecked) with the message 'Cannot convert {val} to byte array for register value'.","triggerScenarios":"Calling getValue(snap) on a DBTraceObjectRegister where the underlying TraceObjectValue for KEY_VALUE holds a type other than byte[] or String — for example, an Integer, Long, Boolean, or a custom object. This happens when the register's value key was set via the generic object model API with an incompatible value type.","commonSituations":"Interoperability issues when the same object key is written by different subsystems (one writes byte[], another writes a numeric type). Trace objects that were populated by a target connector that stored register values as integers rather than byte arrays. Schema evolution where the value type convention changed.","solutions":["Ensure register values are always stored as byte[] or hex String via setValue() — never as other types.","If reading a potentially incompatible value, use the object model directly: object.getValue(snap, KEY_VALUE) and handle the Object type manually.","Convert numeric register values to properly-sized byte arrays before storing them on the register object."],"exampleFix":"// before: storing wrong type\nreg.getObject().setValue(lifespan, TraceRegister.KEY_VALUE, 42);\n\n// after: store as byte[] or hex string\nint len = reg.getByteLength(snap);\nreg.setValue(lifespan,\n    Utils.bigIntegerToBytes(BigInteger.valueOf(42), len, true));","handlingStrategy":"validation","validationCode":"// Check the stored value type before reading\nTraceObjectValue ov = reg.getObject().getValue(snap, TraceRegister.KEY_VALUE);\nif (ov != null) {\n    Object val = ov.getValue();\n    if (!(val instanceof byte[]) && !(val instanceof String)) {\n        // incompatible type; convert or re-store\n        // store as byte[] to fix\n        reg.setValue(Lifespan.at(snap), convertToBytes(val, reg.getByteLength(snap)));\n    }\n}","typeGuard":"// Type guard for safe register value retrieval\nstatic boolean isConvertibleRegisterValue(Object val) {\n    return val instanceof byte[] || val instanceof String;\n}","tryCatchPattern":null,"preventionTips":["Always store register values as byte[] or hex String via setValue().","Never store integers, booleans, or custom objects on the register value key.","Validate stored value types when reading from the generic object model."],"tags":["register","trace-database","type-mismatch","object-model","unchecked-exception"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}