flowable/flowable-engine · error · FlowableIllegalArgumentException

tokenId is null

Error message

tokenId is null

What it means

CreateTokenCmd's constructor validates that a tokenId is supplied before the command is executed by the Flowable IDM engine. If you pass null, the command refuses to run because a token cannot be created or looked up without an identifier. This fail-fast check happens at command construction time, before any database access.

Solutions

  1. Ensure the token id passed to CreateTokenCmd (or the wrapping IdentityService API) is a non-null String before invoking.
  2. If the id comes from a prior lookup, check that the entity exists (query singleResult() != null) before using its id.
  3. Guard the call site: throw a descriptive application exception when the token id is absent so the root cause is visible.
  4. If the token should be auto-generated, use the overload/API that creates a token without requiring a caller-supplied id (TokenServiceImpl.newToken / saveToken).

Example fix

// before
commandExecutor.execute(new CreateTokenCmd(tokenId)); // tokenId may be null

// after
if (tokenId == null) {
    throw new IllegalArgumentException("tokenId must be provided");
}
commandExecutor.execute(new CreateTokenCmd(tokenId));
Defensive patterns

Strategy: validation

Validate before calling

if (tokenId == null || tokenId.isEmpty()) {
    throw new IllegalArgumentException("tokenId must be a non-empty String before creating/looking up a token");
}

Type guard

boolean hasValidTokenId(String tokenId) {
    return tokenId != null && !tokenId.isEmpty();
}

Try / catch

try {
    identityService.saveToken(identityService.newTokenBuilder(tokenId).create());
} catch (FlowableIllegalArgumentException e) {
    if (e.getMessage().contains("tokenId is null")) {
        throw new InvalidRequestException("Token id must not be null");
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling new CreateTokenCmd(null), or invoking an API path that builds this command with a null token id, e.g. IdentityService.createTokenQuery()-style flows or ManagementService APIs that accept a token id which is null.

Common situations: A token id variable read from config, a request parameter, or a previous lookup result is null (entity not found upstream); refactored code paths that no longer populate the id; deserialized DTOs with missing token id fields.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/23a616e39f3e2dff. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-idm-engine/src/main/java/org/flowable/idm/engine/impl/cmd/CreateTokenCmd.java:35

import org.flowable.common.engine.api.FlowableIllegalArgumentException;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.idm.api.Token;
import org.flowable.idm.engine.impl.util.CommandContextUtil;

/**
 * @author Tijs Rademakers
 */
public class CreateTokenCmd implements Command<Token>, Serializable {

    private static final long serialVersionUID = 1L;

    protected String tokenId;

    public CreateTokenCmd(String tokenId) {
        if (tokenId == null) {
            throw new FlowableIllegalArgumentException("tokenId is null");
        }
        this.tokenId = tokenId;
    }

    @Override
    public Token execute(CommandContext commandContext) {
        return CommandContextUtil.getTokenEntityManager(commandContext).createNewToken(tokenId);
    }

}

View on GitHub (pinned to d6d39ce1c6)