{"record":{"id":"a5205532cad89890","repo":"NationalSecurityAgency/ghidra","slug":"mapping-destination-cannot-be-a-traceprogramview","errorCode":null,"errorMessage":"Mapping destination cannot be a TraceProgramView","messagePattern":"Mapping destination cannot be a TraceProgramView","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/modules/DebuggerStaticMappingUtils.java","lineNumber":113,"sourceCode":"\t/**\n\t * Add a static mapping (relocation) from the given trace to the given program\n\t * \n\t * <p>\n\t * Note if the trace is backed by a Ghidra database, the caller must already have started a\n\t * transaction on the relevant domain object.\n\t * \n\t * @param from the source trace location, including lifespan\n\t * @param to the destination program location\n\t * @param length the length of the mapped region\n\t * @param truncateExisting true to delete or truncate the lifespan of overlapping entries\n\t * @throws TraceConflictedMappingException if a conflicting mapping overlaps the source and\n\t *             {@code truncateExisting} is false.\n\t */\n\tpublic static void addMapping(TraceLocation from, ProgramLocation to, long length,\n\t\t\tboolean truncateExisting) throws TraceConflictedMappingException {\n\t\tProgram tp = to.getProgram();\n\t\tif (tp instanceof TraceProgramView) {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\"Mapping destination cannot be a \" + TraceProgramView.class.getSimpleName());\n\t\t}\n\t\tTraceStaticMappingManager manager = from.getTrace().getStaticMappingManager();\n\t\tURL toURL = ProgramURLUtils.getUrlFromProgram(tp);\n\t\tif (toURL == null) {\n\t\t\tnoProject(DebuggerStaticMappingUtils.class);\n\t\t}\n\t\tAddress fromAddress = from.getAddress();\n\t\tAddress toAddress = to.getByteAddress();\n\t\tlong maxFromLengthMinus1 =\n\t\t\tfromAddress.getAddressSpace().getMaxAddress().subtract(fromAddress);\n\t\tlong maxToLengthMinus1 =\n\t\t\ttoAddress.getAddressSpace().getMaxAddress().subtract(toAddress);\n\t\tif (Long.compareUnsigned(length - 1, maxFromLengthMinus1) > 0) {\n\t\t\tthrow new IllegalArgumentException(\"Length would cause address overflow in trace\");\n\t\t}\n\t\tif (Long.compareUnsigned(length - 1, maxToLengthMinus1) > 0) {\n\t\t\tthrow new IllegalArgumentException(\"Length would cause address overflow in program\");","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/modules/DebuggerStaticMappingUtils.java#L95-L131","documentation":"DebuggerStaticMappingUtils.addMapping() maps a trace location to a static program location. The destination must be a real imported Program, not a TraceProgramView (which is a view of a trace presented as a Program). Mappings must go trace -> static program; mapping trace -> trace (via its TraceProgramView) is explicitly rejected to avoid self/cross-trace mapping confusion.","triggerScenarios":"Passing a ProgramLocation whose getProgram() returns a TraceProgramView (i.e. the \"static\" side is actually another trace's view) into addMapping. Programs obtained from a Trace's program view rather than from an imported domain object.","commonSituations":"Scripts that grab a program reference from a trace view and try to map to it. UI actions that have a trace open as a static program and attempt to create a mapping destination from it. Confusing the trace's TraceProgramView with a real static Program.","solutions":["Use a genuine imported static Program (from the project, not a trace view) as the mapping destination.","Obtain the destination program via the project domain-object API rather than trace.getProgramView().","Type-check the destination: if (to.getProgram() instanceof TraceProgramView) reject early and fetch the real program."],"exampleFix":"// before\nProgramLocation dest = new ProgramLocation(trace.getProgramView(), addr);\nDebuggerStaticMappingUtils.addMapping(from, dest, len, false); // throws\n\n// after\nProgram importedStatic = (Program) projectData.getDomainFolder(\"/\").getFile(\"prog\").getImmutableObject();\nProgramLocation dest = new ProgramLocation(importedStatic, addr);\nDebuggerStaticMappingUtils.addMapping(from, dest, len, false);","handlingStrategy":"type-guard","validationCode":"// Reject trace-view destinations before addMapping\nProgram dest = to.getProgram();\nif (dest instanceof TraceProgramView) {\n    throw new IllegalArgumentException(\"Use a real imported Program, not a TraceProgramView\");\n}","typeGuard":"public static boolean isRealStaticProgram(Program p) {\n    return p != null && !(p instanceof TraceProgramView);\n}","tryCatchPattern":"try {\n    DebuggerStaticMappingUtils.addMapping(from, to, length, false);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"TraceProgramView\")) {\n        // fetch the imported static Program and retry\n    } else throw e;\n}","preventionTips":["Source destination programs from the project domain objects, never from trace.getProgramView().","Type-check destination programs with instanceof TraceProgramView before mapping.","Educate script authors that mappings are trace -> static, not trace -> trace."],"tags":["static-mapping","type-guard","trace-model","precondition"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}