apache/incubator-seata · error · IllegalArgumentException

Unknown BranchType[{ordinal}]

Error message

Unknown BranchType[{ordinal}]

What it means

BranchType.get(int) maps a numeric branch type from the protocol back to the BranchType enum (AT, XA, TCC, SAGA). It throws when the ordinal does not match any enum entry, meaning the decoded integer is not a branch type this build knows.

Source

Thrown at core/src/main/java/org/apache/seata/core/model/BranchType.java:73

     * @return the branch type
     */
    public static BranchType get(byte ordinal) {
        return get((int) ordinal);
    }

    /**
     * Get branch type.
     *
     * @param ordinal the ordinal
     * @return the branch type
     */
    public static BranchType get(int ordinal) {
        for (BranchType branchType : values()) {
            if (branchType.ordinal() == ordinal) {
                return branchType;
            }
        }
        throw new IllegalArgumentException("Unknown BranchType[" + ordinal + "]");
    }

    /**
     * Get branch type.
     *
     * @param name the name
     * @return the branch type
     */
    public static BranchType get(String name) {
        for (BranchType branchType : values()) {
            if (branchType.name().equalsIgnoreCase(name)) {
                return branchType;
            }
        }
        throw new IllegalArgumentException("Unknown BranchType[" + name + "]");
    }
}

View on GitHub (pinned to e01f97c6db)

Solutions

  1. Align Seata versions on both ends of the RPC connection.
  2. Ensure point-to-point TCP between RM/TM and TC — no HTTP-style proxies or middleboxes rewriting the stream.
  3. Enable protocol debug logs (org.apache.seata.rpc) and inspect the failing RpcMessage id/type to locate which message decodes badly.

Example fix

# before: mixed versions
rm seata 1.4 -> tc seata 2.2
# after
rm seata 2.2 -> tc seata 2.2
Defensive patterns

Strategy: type-guard

Validate before calling

static boolean validBranchOrdinal(int o) {
    for (BranchType b : BranchType.values()) if (b.ordinal() == o) return true;
    return false;
}

Type guard

static Optional<BranchType> safeBranch(int o) {
    return Arrays.stream(BranchType.values()).filter(b -> b.ordinal() == o).findFirst();
}

Try / catch

catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("Unknown BranchType")) { closeChannelSafely(); LOG.warn("protocol mismatch: {}", e.getMessage()); }
    else throw e;
}

Prevention

When it happens

Trigger: A branch register/undo message arrives carrying a branch-type byte outside 0..3 for this version, or protocol bytes are misaligned/corrupt so a different field is read as the branch type.

Common situations: Version skew (a future enum entry sent to an old build), non-Seata clients on the TC port, or framing corruption introduced by a TCP proxy that modifies the byte stream.

Related errors


AI-assisted analysis of apache/incubator-seata@e01f97c6db (2026-08-14). Data as JSON: /api/errors/46c6bb755b6b6594. Report an issue: GitHub.