{"record":{"id":"88fae18cf489d83c","repo":"alibaba/DataX","slug":"transformer-run-exception","errorCode":"TRANSFORMER_RUN_EXCEPTION","errorMessage":"dx_replace startIndex(%s) out of range(%s)","messagePattern":"dx_replace startIndex\\((.+?)\\) out of range\\((.+?)\\)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/com/alibaba/datax/core/transport/transformer/ReplaceTransformer.java","lineNumber":51,"sourceCode":"            startIndex = Integer.valueOf((String) paras[1]);\n            length = Integer.valueOf((String) paras[2]);\n            replaceString = (String) paras[3];\n        } catch (Exception e) {\n            throw DataXException.asDataXException(TransformerErrorCode.TRANSFORMER_ILLEGAL_PARAMETER, \"paras:\" + Arrays.asList(paras).toString() + \" => \" + e.getMessage());\n        }\n\n        Column column = record.getColumn(columnIndex);\n\n        try {\n            String oriValue = column.asString();\n\n            //如果字段为空，跳过replace处理\n            if(oriValue == null){\n                return  record;\n            }\n            String newValue;\n            if (startIndex > oriValue.length()) {\n                throw new RuntimeException(String.format(\"dx_replace startIndex(%s) out of range(%s)\", startIndex, oriValue.length()));\n            }\n            if (startIndex + length >= oriValue.length()) {\n                newValue = oriValue.substring(0, startIndex) + replaceString;\n            } else {\n                newValue = oriValue.substring(0, startIndex) + replaceString + oriValue.substring(startIndex + length, oriValue.length());\n            }\n\n            record.setColumn(columnIndex, new StringColumn(newValue));\n\n        } catch (Exception e) {\n            throw DataXException.asDataXException(TransformerErrorCode.TRANSFORMER_RUN_EXCEPTION, e.getMessage(),e);\n        }\n        return record;\n    }\n}\n","sourceCodeStart":33,"sourceCodeEnd":67,"githubUrl":"https://github.com/alibaba/DataX/blob/80ec23d5c5328eb90ca364d2749e92dfaf44541e/core/src/main/java/com/alibaba/datax/core/transport/transformer/ReplaceTransformer.java#L33-L67","documentation":"Thrown by dx_replace when startIndex exceeds the length of the column's string value, because String.substring cannot begin past the end of the string. The value is read per record via column.asString() (null values are skipped), so this is a data-dependent runtime error wrapped as TRANSFORMER_RUN_EXCEPTION, not a configuration error.","triggerScenarios":"A record whose target column contains a string shorter than startIndex, e.g. startIndex=5 applied to the value \"abc\". The comparison is strict (startIndex > length), so startIndex == length is allowed and produces a pure append; anything greater throws.","commonSituations":"Fixed startIndex chosen against the longest expected value, but the source table later contains shorter rows; null-vs-empty-string confusion (empty strings are processed, nulls are skipped); multi-byte characters where Java length counts UTF-16 chars.","solutions":["Lower startIndex so it is <= the length of the shortest non-null value in the column.","Pre-filter or pad short values with dx_pad before dx_replace in the transformer chain.","Inspect the failing record (the DataX log shows the record and column index) to see the actual short value and adjust the parameters accordingly."],"exampleFix":"// before: value \"abc\", startIndex 5\n\"paras\": [2, \"5\", \"3\", \"X\"]\n// after: start within shortest value\n\"paras\": [2, \"2\", \"3\", \"X\"]","handlingStrategy":"validation","validationCode":"// before applying dx_replace, ensure every non-null value is long enough\nString v = record.getColumn(idx).asString();\nif (v != null && v.length() < startIndex) {\n    v = String.format(\"%-\" + startIndex + \"s\", v); // pad right to safe length\n    record.setColumn(idx, new StringColumn(v));\n}","typeGuard":null,"tryCatchPattern":"catch (DataXException e) when TRANSFORMER_RUN_EXCEPTION: log record + column value, route record to a dirty channel instead of aborting the task.","preventionTips":["Profile MIN(LEN(col)) on the source before choosing startIndex.","Chain dx_pad ahead of dx_replace to guarantee minimum width."],"tags":["datax","transformer","dx-replace","data-dependent"],"backgroundTag":null,"analyzedSha":"80ec23d5c5328eb90ca364d2749e92dfaf44541e","analyzedAt":"2026-08-14T15:33:51.187Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}