{"record":{"id":"9c68bb582f525906","repo":"NationalSecurityAgency/ghidra","slug":"an-external-address-translator-can-only-handle-a-s","errorCode":null,"errorMessage":"An external address translator can only handle a single address at a time, if that.","messagePattern":"An external address translator can only handle a single address at a time, if that\\.","errorType":"exception","errorClass":"AddressTranslationException","httpStatus":null,"severity":"error","filePath":"Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/ExternalsAddressTranslator.java","lineNumber":85,"sourceCode":"\t\tif (destinationAddress != null) {\n\t\t\treturn destinationAddress;\n\t\t}\n\t\tthrow new AddressTranslationException(\n\t\t\t\"The specified source address never had an external address pair added to the translator.\");\n\t}\n\n\t@Override\n\tpublic boolean isOneForOneTranslator() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic AddressSet getAddressSet(AddressSetView sourceAddressSet) {\n\t\tif (sourceAddressSet == null) {\n\t\t\treturn null;\n\t\t}\n\t\tif (sourceAddressSet.getNumAddresses() > 1) {\n\t\t\tthrow new AddressTranslationException(\n\t\t\t\t\"An external address translator can only handle a single address at a time, if that.\");\n\t\t}\n\t\tAddressSet destinationSet = new AddressSet();\n\t\tif (sourceAddressSet.isEmpty()) {\n\t\t\treturn destinationSet;\n\t\t}\n\t\tAddress sourceAddress = sourceAddressSet.getMinAddress();\n\t\tAddress destinationAddress = addressMap.get(sourceAddress);\n\t\tif (destinationAddress != null) {\n\t\t\tdestinationSet.add(destinationAddress);\n\t\t}\n\t\tthrow new AddressTranslationException(\n\t\t\t\"The specified source address set never had an external address pair added to the translator.\");\n\t}\n\n\t@Override\n\tpublic AddressRange getAddressRange(AddressRange sourceAddressRange)\n\t\t\tthrows AddressTranslationException {","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/ExternalsAddressTranslator.java#L67-L103","documentation":"Thrown as AddressTranslationException by ExternalsAddressTranslator.getAddressSet when the supplied AddressSetView contains more than one address. ExternalsAddressTranslator is declared one-for-one (isOneForOneTranslator() returns true) because external locations are individually mapped, so a multi-address set is unsupported by design.","triggerScenarios":"Passing an AddressSetView with getNumAddresses() > 1 into getAddressSet — for example the result of a listing address set, a memory range set, or a diff address set that was not narrowed to a single external location.","commonSituations":"Feeding a whole-function or whole-block address set into a translator built only for external single addresses; reusing a generic ProgramMerge translator on external space without splitting it.","solutions":["Split the AddressSetView into single-address sets (or iterate Address by Address) before translation.","Use a different AddressTranslator implementation that supports ranges for non-external spaces.","Filter the set down to a single external location via intersection with the external address space."],"exampleFix":"// before\nAddressSet out = translator.getAddressSet(multiAddrSet); // throws\n\n// after — translate one address at a time\nAddressSet out = new AddressSet();\nfor (Address src : multiAddrSet.getAddresses(true)) {\n    translator.setPair(mappedDest(src), src);\n    out.add(translator.getAddress(src));\n}","handlingStrategy":"validation","validationCode":"if (sourceAddressSet == null || sourceAddressSet.getNumAddresses() > 1) {\n    // translate address-by-address instead\n    AddressSet out = new AddressSet();\n    for (Address a : sourceAddressSet.getAddresses(true)) {\n        translator.setPair(map(a), a);\n        out.add(translator.getAddress(a));\n    }\n    return out;\n}","typeGuard":"boolean safeForSet = sourceAddressSet != null && sourceAddressSet.getNumAddresses() <= 1;","tryCatchPattern":"try {\n    return translator.getAddressSet(sourceAddressSet);\n} catch (AddressTranslationException e) {\n    // fall back to per-address translation\n}","preventionTips":["Never pass a multi-address set to a one-for-one external translator.","Split sets into singletons for external address spaces.","Check isOneForOneTranslator() before bulk translation."],"tags":["ghidra","merge","address-translator","validation"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}