apache/incubator-seata · error · IllegalArgumentException

The default branch type must be AT or XA. the value of the a

Error message

The default branch type must be AT or XA. the value of the argument is: {defaultBranchType}

What it means

RootContext.setDefaultBranchType rejects any BranchType other than AT or XA. The default branch type is what getBranchType() falls back to when a binding is absent, and only resource-managed branch modes (AT/XA) are valid defaults — TCC and SAGA are always explicitly bound by their interceptors, so they cannot be defaults.

Source

Thrown at core/src/main/java/org/apache/seata/core/context/RootContext.java:98

     */
    public static final String HIDDEN_KEY_BRANCH_TYPE = Constants.HIDE_KEY_PREFIX_CHAR + KEY_BRANCH_TYPE;

    /**
     * The constant KEY_GLOBAL_LOCK_FLAG, VALUE_GLOBAL_LOCK_FLAG
     */
    public static final String KEY_GLOBAL_LOCK_FLAG = "TX_LOCK";

    public static final Boolean VALUE_GLOBAL_LOCK_FLAG = true;

    private static ContextCore CONTEXT_HOLDER = ContextCoreLoader.load();

    private static BranchType DEFAULT_BRANCH_TYPE;

    public static final String KEY_COMBINE_TRANSACTION_FLAG = "TX_COMBINE";

    public static void setDefaultBranchType(BranchType defaultBranchType) {
        if (defaultBranchType != AT && defaultBranchType != XA) {
            throw new IllegalArgumentException("The default branch type must be " + AT + " or " + XA + "."
                    + " the value of the argument is: " + defaultBranchType);
        }
        if (DEFAULT_BRANCH_TYPE != null && DEFAULT_BRANCH_TYPE != defaultBranchType && LOGGER.isWarnEnabled()) {
            LOGGER.warn(
                    "The `{}.DEFAULT_BRANCH_TYPE` has been set repeatedly. The value changes from {} to {}",
                    RootContext.class.getSimpleName(),
                    DEFAULT_BRANCH_TYPE,
                    defaultBranchType);
        }
        DEFAULT_BRANCH_TYPE = defaultBranchType;
    }

    /**
     * Gets xid.
     *
     * @return the xid
     */
    @Nullable

View on GitHub (pinned to e01f97c6db)

Solutions

  1. Use only AT or XA for the default branch type: seata.client.default-branch-type=at (or xa).
  2. For TCC/SAGA participation, let the @TwoPhaseBusiness/@GlobalTransactional-type annotations and interceptors bind the branch type explicitly; do not set it as default.
  3. Remove custom calls to setDefaultBranchType with non-AT/XA values.

Example fix

# before
seata.client.default-branch-type=tcc
# after
seata.client.default-branch-type=xa
Defensive patterns

Strategy: validation

Validate before calling

BranchType t = BranchType.get(cfgValue);
if (t != BranchType.AT && t != BranchType.XA) {
    throw new ConfigException("default-branch-type only allows AT or XA, got: " + cfgValue);
}

Type guard

boolean isValidDefault(BranchType t) { return t == BranchType.AT || t == BranchType.XA; }

Prevention

When it happens

Trigger: Calling RootContext.setDefaultBranchType(BranchType.TCC) or (SAGA) programmatically, or configuring the client default branch type property as 'TCC'/'SAGA' which is read at startup and pushed into this method.

Common situations: Team sets seata.client.default-branch-type=tcc believing it will make @TwoPhaseBusiness methods behave like a default, or migrates a config where branch type semantics were misunderstood; also custom bootstrap code that copies an explicit bind into the default.

Related errors


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