{"record":{"id":"4b23842601d0de02","repo":"apache/pulsar","slug":"invalid-txnid-key","errorCode":null,"errorMessage":"Invalid txnId key: ","messagePattern":"Invalid txnId key: ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-broker/src/main/java/org/apache/pulsar/broker/transaction/metadata/TxnIds.java","lineNumber":49,"sourceCode":" * single point that controls the on-the-wire encoding.\n */\npublic final class TxnIds {\n\n    private static final char SEP = '_';\n\n    /** @return {@code <most>_<least>}, suitable for use as a metadata-store path segment. */\n    public static String toKey(TxnID txnId) {\n        return txnId.getMostSigBits() + String.valueOf(SEP) + txnId.getLeastSigBits();\n    }\n\n    /**\n     * @return the {@link TxnID} parsed from {@code key}.\n     * @throws IllegalArgumentException if {@code key} is not in the expected {@code <most>_<least>} form\n     */\n    public static TxnID fromKey(String key) {\n        int sep = key.indexOf(SEP);\n        if (sep <= 0 || sep == key.length() - 1 || key.indexOf(SEP, sep + 1) >= 0) {\n            throw new IllegalArgumentException(\"Invalid txnId key: \" + key);\n        }\n        long most = Long.parseLong(key, 0, sep, 10);\n        long least = Long.parseLong(key, sep + 1, key.length(), 10);\n        return new TxnID(most, least);\n    }\n\n    private TxnIds() {}\n}\n","sourceCodeStart":31,"sourceCodeEnd":58,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker/src/main/java/org/apache/pulsar/broker/transaction/metadata/TxnIds.java#L31-L58","documentation":"TxnIds.fromKey parses a transaction id key string of the form '<most>_<least>' back into a TxnID. It throws IllegalArgumentException when the key is not a well-formed pair of longs separated by exactly one underscore. This guards against corrupted or hand-crafted keys being silently mis-parsed.","triggerScenarios":"Calling TxnIds.fromKey with a string that has no underscore, an underscore at the start or end, more than one underscore, or non-numeric segments (which also throws NumberFormatException from Long.parseLong).","commonSituations":"Restoring/inspecting transaction metadata where keys were serialized by a different version or format; manually constructed keys in tests or tools; keys containing a trailing separator; using a ledger/bookkeeper entry id string instead of a txnId key.","solutions":["Print and inspect the offending key string; ensure it is exactly '<most>_<least>' with numeric segments","Use TxnIds.newKey(TxnID) (the pairing write path) to generate keys instead of building strings manually","Strip any accidental prefix/suffix (e.g. topic or partition prefixes) before parsing","If the key may be malformed, pre-validate with a regex like ^\\d+_\\d+$ before calling fromKey"],"exampleFix":"// before\nTxnID txn = TxnIds.fromKey(userInput); // may throw\n// after\nif (userInput != null && userInput.matches(\"\\\\d+_\\\\d+\")) {\n    TxnID txn = TxnIds.fromKey(userInput);\n} else {\n    log.warn(\"Skipping malformed txnId key: {}\", userInput);\n}","handlingStrategy":"validation","validationCode":"private static final java.util.regex.Pattern TXN_KEY = java.util.regex.Pattern.compile(\"\\\\d+_\\\\d+\");\npublic static TxnID safeFromKey(String key) {\n    if (key == null || !TXN_KEY.matcher(key).matches()) {\n        return null; // or throw a domain-specific error\n    }\n    return TxnIds.fromKey(key);\n}","typeGuard":"public static boolean isValidTxnKey(String key) {\n    return key != null && key.matches(\"\\\\d+_\\\\d+\");\n}","tryCatchPattern":"try {\n    TxnID txn = TxnIds.fromKey(key);\n} catch (IllegalArgumentException e) {\n    log.warn(\"Skipping malformed txnId key: {}\", key, e);\n    // skip or quarantine the key\n}","preventionTips":["Always generate keys via TxnIds.newKey / the library's pairing method instead of string concatenation","Validate keys with a \\d+_\\d+ regex before parsing","Beware Long.parseLong inside fromKey also throwing NumberFormatException on huge/overflowing segments","Log the raw key value when reporting parse failures"],"tags":["transaction","parsing","illegal-argument"],"backgroundTag":"malformed-transaction-id-key","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}