flowable/flowable-engine · error · ActivitiIllegalArgumentException

deploymentId is null

Error message

deploymentId is null

What it means

Activiti/Flowable's ChangeDeploymentTenantIdCmd changes the tenantId of a deployment and its related definitions, instances and tasks. Before doing any work it validates that a deploymentId was supplied; a null id is rejected immediately as an illegal argument because no lookup or update is possible without it.

Solutions

  1. Ensure a non-null deploymentId is passed to changeDeploymentTenantId
  2. Log/validate the id at the call site before invoking the command
  3. Fix the upstream source (config property, variable, lookup) that yields null

Example fix

// before
managementService.changeDeploymentTenantId(deploymentId, "tenant-2");
// after
if (deploymentId == null) throw new IllegalArgumentException("deploymentId required");
managementService.changeDeploymentTenantId(deploymentId, "tenant-2");
Defensive patterns

Strategy: validation

Validate before calling

if (deploymentId == null || deploymentId.isEmpty()) throw new IllegalArgumentException("deploymentId required before changeDeploymentTenantId");

Type guard

boolean hasDeploymentId(String id) { return id != null && !id.trim().isEmpty(); }

Try / catch

try { managementService.changeDeploymentTenantId(id, tenant); } catch (ActivitiIllegalArgumentException e) { log.error("Bad argument: {}", e.getMessage()); }

Prevention

When it happens

Trigger: Calling managementService.changeDeploymentTenantId(deploymentId, newTenantId) (or executing ChangeDeploymentTenantIdCmd directly) with a null deploymentId, e.g. an unresolved variable or an unset config field passed through.

Common situations: Deployments created via a different API that returns null id on failure; wiring a tenant-id change into a batch script where the deployment id comes from a properties file or env var that is empty; passing a variable that was never initialized.

Related errors


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

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cmd/ChangeDeploymentTenantIdCmd.java:44

/**
 * @author Joram Barrez
 */
public class ChangeDeploymentTenantIdCmd implements Command<Void>, Serializable {

    private static final long serialVersionUID = 1L;

    protected String deploymentId;
    protected String newTenantId;

    public ChangeDeploymentTenantIdCmd(String deploymentId, String newTenantId) {
        this.deploymentId = deploymentId;
        this.newTenantId = newTenantId;
    }

    @Override
    public Void execute(CommandContext commandContext) {
        if (deploymentId == null) {
            throw new ActivitiIllegalArgumentException("deploymentId is null");
        }

        // Update all entities

        DeploymentEntity deployment = commandContext.getDeploymentEntityManager().findDeploymentById(deploymentId);
        if (deployment == null) {
            throw new ActivitiObjectNotFoundException("Could not find deployment with id " + deploymentId, Deployment.class);
        }
        String oldTenantId = deployment.getTenantId();
        deployment.setTenantId(newTenantId);

        // Doing process instances, executions and tasks with direct SQL updates (otherwise would not be performant)
        commandContext.getProcessDefinitionEntityManager().updateProcessDefinitionTenantIdForDeployment(deploymentId, newTenantId);
        commandContext.getExecutionEntityManager().updateExecutionTenantIdForDeployment(deploymentId, newTenantId);
        commandContext.getTaskEntityManager().updateTaskTenantIdForDeployment(deploymentId, newTenantId);
        commandContext.getJobEntityManager().updateJobTenantIdForDeployment(deploymentId, newTenantId);
        commandContext.getTimerJobEntityManager().updateTimerJobTenantIdForDeployment(deploymentId, newTenantId);
        commandContext.getSuspendedJobEntityManager().updateSuspendedJobTenantIdForDeployment(deploymentId, newTenantId);

View on GitHub (pinned to d6d39ce1c6)