{"record":{"id":"5d5fd6eea4cc7ff7","repo":"languagetool-org/languagetool","slug":"could-not-map-plaintextposition-to-original-po","errorCode":null,"errorMessage":"Could not map + plainTextPosition + to original position. Mapping: + mapping","messagePattern":"Could not map \\+ plainTextPosition \\+ to original position\\. Mapping: \\+ mapping","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"languagetool-wikipedia/src/main/java/org/languagetool/dev/wikipedia/PlainTextMapping.java","lineNumber":75,"sourceCode":"      return origPosition;\n    }\n    int minDiff = Integer.MAX_VALUE;\n    Location bestMatch = null;\n    //Integer bestMaybeClosePosition = null;\n    // algorithm: find the closest lower position\n    for (Map.Entry<Integer, Location> entry : mapping.entrySet()) {\n      int maybeClosePosition = entry.getKey();\n      if (plainTextPosition > maybeClosePosition) {\n        int diff = plainTextPosition - maybeClosePosition;\n        if (diff >= 0 && diff < minDiff) {\n          bestMatch = entry.getValue();\n          //bestMaybeClosePosition = maybeClosePosition;\n          minDiff = diff;\n        }\n      }\n    }\n    if (bestMatch == null) {\n      throw new RuntimeException(\"Could not map \" + plainTextPosition + \" to original position. Mapping: \" + mapping);\n    }\n    // we assume that when we have found the closest match there's a one-to-one mapping\n    // in this region, thus we can add 'minDiff' to get the exact position:\n    //System.out.println(\"mapping \" + plainTextPosition + \" to line \" + bestMatch.line + \", column \" +\n    //        bestMatch.column + \"+\" +  minDiff + \", bestMatch was: \" + bestMaybeClosePosition +\"=>\"+ bestMatch);\n    return new Location(bestMatch.file, bestMatch.line, bestMatch.column + minDiff);\n  }\n\n}\n","sourceCodeStart":57,"sourceCodeEnd":85,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-wikipedia/src/main/java/org/languagetool/dev/wikipedia/PlainTextMapping.java#L57-L85","documentation":"getOriginalTextPositionFor first tries an exact mapping entry; if none exists it searches the closest known position. If no bestMatch could be found at all (mapping empty or positions wildly outside it), it throws this RuntimeException stating the position could not be mapped.","triggerScenarios":"Requesting a plainTextPosition that has no entry in the mapping and no plausible nearby entry — usually a position beyond the converted text length or an empty mapping (built without enableMapping).","commonSituations":"Mapping positions from a different text version than the one converted; calling getMapping while mapping was never enabled so it is empty; position past end of document after edits.","solutions":["Ensure the position comes from the same converted text the mapping was built from","Enable mapping at conversion time (enableMapping) so the map is populated","Validate plainTextPosition <= converted text length before querying","Fall back to nearest documented line/column when exact mapping is unavailable"],"exampleFix":"// before\nLocation loc = converter.getMapping().get(...); // mapping empty\n// after\nconverter.setEnableMapping(true);\nString plain = converter.convert(originalText); // build mapping before querying","handlingStrategy":"validation","validationCode":"if (!converter.isEnableMapping() || plainTextPosition > converter.getConvertedTextLength()) {\n  throw new IllegalArgumentException(\"position unmappable: \" + plainTextPosition);\n}","typeGuard":null,"tryCatchPattern":"try {\n  loc = mapping.getOriginalTextPositionFor(pos);\n} catch (RuntimeException e) {\n  loc = approximateLocation(pos); // fallback to nearest computed line/col\n}","preventionTips":["Enable mapping before converting so the map is populated","Only query positions from the same converted text","Keep original and converted text versions in sync"],"tags":["position-mapping","wikipedia","mapping"],"backgroundTag":"invalid-argument-value","analyzedSha":"2e990059ce67d5e2a0f7f7ca5d31160c6709df4b","analyzedAt":"2026-09-06T09:20:17.015Z","contentChangedAt":"2026-09-06T09:20:17.015Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}