flowable/flowable-engine · error · FlowableException
Error reading json value ${configuration}
Error message
Error reading json value ${configuration} What it means
TimerSuspendProcessDefinitionHandler parses its job handler configuration string as JSON to read the 'includeProcessInstances' flag; if readTree or the flag extraction throws, the handler wraps the failure in FlowableException('Error reading json value ' + configuration). The raw configuration text is embedded in the message to aid diagnosis.
Source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/jobexecutor/TimerSuspendProcessDefinitionHandler.java:45
public class TimerSuspendProcessDefinitionHandler extends TimerChangeProcessDefinitionSuspensionStateJobHandler {
public static final String TYPE = "suspend-processdefinition";
@Override
public String getType() {
return TYPE;
}
@Override
public void execute(Job job, String configuration, ExecutionEntity execution, CommandContext commandContext) {
ProcessEngineConfigurationImpl processEngineConfiguration = commandContext.getProcessEngineConfiguration();
boolean suspendProcessInstances = false;
try {
JsonNode configNode = processEngineConfiguration.getObjectMapper().readTree(configuration);
suspendProcessInstances = getIncludeProcessInstances(configNode);
} catch (Exception e) {
throw new FlowableException("Error reading json value " + configuration, e);
}
String processDefinitionId = job.getProcessDefinitionId();
SuspendProcessDefinitionCmd suspendProcessDefinitionCmd = new SuspendProcessDefinitionCmd(processDefinitionId, null, suspendProcessInstances, null, job.getTenantId());
suspendProcessDefinitionCmd.execute(commandContext);
}
}
View on GitHub (pinned to d6d39ce1c6)
Solutions
- Inspect the job's configuration (ACT_RU_JOB.JOB_HANDLER_CFG_) and fix it to the JSON shape the current version expects: {"includeProcessInstances":true|false,"processDefinitionId":"..."} or delete the stale job
- Align engine versions: run the upgrade job-cfg migration scripts or ensure all cluster nodes run the same Flowable version
- Suspend the definition manually to achieve the intended effect: repositoryService.suspendProcessDefinitionById(id, true, null), then remove the broken job
- Recreate the scenario if needed via a fresh ProcessDefinitionSuspension schedule so the engine writes a well-formed configuration
Example fix
// before: corrupted job config, job keeps failing // after: suspend manually and remove the failing job repositoryService.suspendProcessDefinitionById(processDefinitionId, true, null); Job job = managementService.createJobQuery().jobId(jobId).singleResult(); managementService.deleteJob(job.getId());
Defensive patterns
Strategy: validation
Validate before calling
ObjectNode cfg = objectMapper.createObjectNode();
cfg.put("includeProcessInstances", true);
// store cfg.toString() as the job handler configuration; verify before firing:
JsonNode n = objectMapper.readTree(job.getJobHandlerConfiguration());
if (!n.has("includeProcessInstances")) throw new IllegalStateException("malformed suspension job config: " + job.getJobHandlerConfiguration()); Type guard
boolean isValidSuspensionConfig(String cfg) {
try {
JsonNode n = objectMapper.readTree(cfg);
return n != null && n.has("includeProcessInstances") && n.get("includeProcessInstances").isBoolean();
} catch (Exception e) { return false; }
} Try / catch
try {
managementService.executeJob(suspendJobId);
} catch (FlowableException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Error reading json value")) {
log.error("corrupt suspension job cfg: {}", e.getMessage());
managementService.deleteJob(suspendJobId); // or repair cfg then re-execute
} else { throw e; }
} Prevention
- Never hand-edit ACT_RU_JOB.JOB_HANDLER_CFG_ contents; recreate jobs through the API instead
- Run identical Flowable versions on every cluster node (job config formats differ across versions)
- Apply upgrade scripts when migrating so old job configurations are converted
- Prefer repositoryService.suspendProcessDefinitionById for one-off suspensions instead of crafting timer jobs manually
When it happens
Trigger: A suspend-process-definition timer job whose JOB_HANDLER_CFG_ column is not valid JSON, or valid JSON lacking the expected includeProcessInstances field that getIncludeProcessInstances requires.
Common situations: Jobs written by an older engine version read by a newer one after upgrade (config schema changed); manual edits or data migrations that corrupted the configuration column; copying jobs across environments with mismatched engine versions.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- Error reading json value " + configuration + " for job " + j
- Error reading json value " + configuration + " for " + job
- Error reading json value ${configuration}
- Error reading app resource
- Error writing app model to json
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/4aa2e2ec9e51d018.
Report an issue: GitHub.