{"record":{"id":"c317ee412003476a","repo":"NationalSecurityAgency/ghidra","slug":"failed-to-read-len-bytes-at-addr","errorCode":null,"errorMessage":"Failed to read {len} bytes at {addr}","messagePattern":"Failed to read (.+?) bytes at (.+?)","errorType":"exception","errorClass":"MemoryAccessException","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceInstruction.java","lineNumber":654,"sourceCode":"\tpublic int getParsedLength() {\n\t\tif (lengthOverride == 0) {\n\t\t\treturn super.getLength();\n\t\t}\n\t\treturn getPrototype().getLength();\n\t}\n\n\t@Override\n\tpublic byte[] getParsedBytes() throws MemoryAccessException {\n\t\tif (!isLengthOverridden()) {\n\t\t\treturn getBytes();\n\t\t}\n\t\ttry (LockHold hold = LockHold.lock(space.lock.readLock())) {\n\t\t\trefreshIfNeeded();\n\t\t\tint len = getPrototype().getLength();\n\t\t\tbyte[] b = new byte[len];\n\t\t\tAddress addr = getAddress();\n\t\t\tif (len != getMemory().getBytes(addr, b)) {\n\t\t\t\tthrow new MemoryAccessException(\"Failed to read \" + len + \" bytes at \" + addr);\n\t\t\t}\n\t\t\treturn b;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setFallThrough(Address fallThrough) {\n\t\ttry (LockHold hold = space.trace.lockWrite()) {\n\t\t\tcheckDeleted();\n\t\t\tAddress defaultFallThrough = prototype.getFallThrough(this);\n\t\t\tif (Objects.equals(fallThrough, defaultFallThrough)) {\n\t\t\t\tclearFallThroughOverride();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (fallThrough == null) {\n\t\t\t\tclearFallThroughRefs(null);\n\t\t\t\tsetFallThroughOverridden(true);\n\t\t\t}","sourceCodeStart":636,"sourceCodeEnd":672,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceInstruction.java#L636-L672","documentation":"Thrown by DBTraceInstruction.getParsedBytes() when the instruction has a length override (isLengthOverridden() is true) and the trace memory cannot supply the prototype's expected number of bytes at the instruction's address. The method reads len bytes (from getPrototype().getLength()) via getMemory().getBytes(addr, b) and if the returned count differs from len, a MemoryAccessException is raised. This is a checked exception, signalling that the backing memory for this instruction is missing, partially initialized, or has been truncated in the trace database.","triggerScenarios":"Calling getParsedBytes() on a DBTraceInstruction whose isLengthOverridden() returns true, when the underlying trace memory space does not contain enough bytes at the instruction's address. This occurs when memory state at the relevant snap is UNKNOWN or only partially written, or when the instruction was created with a forced length override that exceeds available memory.","commonSituations":"During debugger/emulator trace replay when memory was never recorded for the instruction's snap. After importing a partial trace where code units reference memory regions that were not captured. When an instruction's length was overridden to a value larger than the recorded memory block.","solutions":["Ensure the trace memory at the instruction's address and snap is fully recorded before calling getParsedBytes() — write bytes via TraceMemorySpace.putBytes() first.","Check the instruction's memory state with getState(snap) == TraceMemoryState.KNOWN before requesting parsed bytes.","If length override is unnecessary, avoid setting it so getParsedBytes() delegates to getBytes() which may handle partial reads differently.","Wrap the call in try-catch for MemoryAccessException and fall back to getBytes() or skip the instruction if memory is unavailable."],"exampleFix":"// before\nbyte[] parsed = instruction.getParsedBytes();\n\n// after\nif (instruction.isLengthOverridden() &&\n    memory.getState(instruction.getStartSnap(), instruction.getAddress()) != TraceMemoryState.KNOWN) {\n    // populate or skip\n} else {\n    byte[] parsed = instruction.getParsedBytes();\n}","handlingStrategy":"validation","validationCode":"// Before calling getParsedBytes(), check memory state and length\nTraceMemorySpace mem = instruction.getMemory();\nlong snap = instruction.getStartSnap();\nAddress addr = instruction.getAddress();\nif (mem.getState(snap, addr) != TraceMemoryState.KNOWN) {\n    // memory not available; handle gracefully\n    return;\n}\nint expectedLen = instruction.getPrototype().getLength();\n// optionally verify bytes are readable\nbyte[] test = new byte[expectedLen];\nif (mem.getBytes(addr, test) != expectedLen) {\n    // insufficient bytes\n    return;\n}","typeGuard":null,"tryCatchPattern":"try {\n    byte[] parsed = instruction.getParsedBytes();\n} catch (MemoryAccessException e) {\n    // memory unavailable for this instruction's snap\n    // fall back to getBytes() or skip\n    logger.warning(\"No parsed bytes at \" + instruction.getAddress() + \": \" + e.getMessage());\n}","preventionTips":["Always record memory for instruction addresses before accessing parsed bytes.","Check TraceMemoryState.KNOWN before calling getParsedBytes().","Avoid unnecessary length overrides that may exceed available memory."],"tags":["memory-access","trace-database","instruction","checked-exception"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}