flowable/flowable-engine · error · FlowableObjectNotFoundException

Could not find a form data with id '" + id + "'.

Error message

Could not find a form data with id '" + id + "'.

What it means

Flowable's REST form-data endpoint throws FlowableObjectNotFoundException when neither the taskId nor the processDefinitionId resolves to actual form metadata. After looking up start-form or task-form data, the service checks whether the FormData object is null and throws, embedding the id that failed to resolve. It means the referenced form (or the task/process definition owning it) does not exist or has no form attached.

Solutions

  1. Verify the taskId or processDefinitionId exists via the task/process-definition REST endpoints before requesting form data
  2. Ensure the process definition actually declares a form (formKey on the start event or task) before querying form data
  3. Catch FlowableObjectNotFoundException (HTTP 404) and surface a user-friendly 'form not found' message
  4. Re-fetch the current process definition id after a redeploy instead of caching the old one

Example fix

// before
curl http://localhost:8080/flowable-rest/form/form-data?processDefinitionId=oldDefId:1:4

// after
// redeploy lookup: get latest definition first
curl "http://localhost:8080/flowable-rest/repository/process-definitions?key=myProcess&latest=true"
// then use the returned id:
curl "http://localhost:8080/flowable-rest/form/form-data?processDefinitionId=<latestId>"
Defensive patterns

Strategy: validation

Validate before calling

const exists = await fetch(`${BASE}/repository/process-definitions/${processDefinitionId}`).then(r => r.ok);
if (!exists) throw new Error(`Process definition ${processDefinitionId} not found`);

Type guard

function hasFormTarget(req) { return typeof req.taskId === 'string' && req.taskId.length > 0 || typeof req.processDefinitionId === 'string' && req.processDefinitionId.length > 0; }

Try / catch

try { const form = await getFormData(taskId); } catch (e) { if (e.status === 404) showFormNotFound(e); else throw e; }

Prevention

When it happens

Trigger: GET /form/form-data with a taskId that has no associated task form, or a processDefinitionId that has no start form defined; nonexistent taskId/processDefinitionId values; deleted process definitions.

Common situations: Client passes a stale processDefinitionId after redeploying a new version; process has no <startEvent ... flowable:formKey> yet endpoint is queried; typo in taskId.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/form/FormDataResource.java:87

            throw new FlowableIllegalArgumentException("The taskId or processDefinitionId parameter has to be provided");
        }

        if (taskId != null && processDefinitionId != null) {
            throw new FlowableIllegalArgumentException("Not both a taskId and a processDefinitionId parameter can be provided");
        }

        FormData formData = null;
        String id = null;
        if (taskId != null) {
            formData = formService.getTaskFormData(taskId);
            id = taskId;
        } else {
            formData = formService.getStartFormData(processDefinitionId);
            id = processDefinitionId;
        }

        if (formData == null) {
            throw new FlowableObjectNotFoundException("Could not find a form data with id '" + id + "'.", FormData.class);
        }
        
        if (restApiInterceptor != null) {
            restApiInterceptor.accessFormData(formData);
        }

        return restResponseFactory.createFormDataResponse(formData);
    }

    @ApiOperation(value = "Submit task form data", tags = { "Forms" })
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Indicates request was successful and the form data was submitted"),
            @ApiResponse(code = 204, message = "If TaskId has been provided, Indicates request was successful and the form data was submitted. Returns empty"),
            @ApiResponse(code = 400, message = "Indicates an parameter was passed in the wrong format. The status-message contains additional information.") })
    @PostMapping(value = "/form/form-data", produces = "application/json")
    public ProcessInstanceResponse submitForm(@RequestBody SubmitFormRequest submitRequest, HttpServletResponse response) {

        if (submitRequest == null) {

View on GitHub (pinned to d6d39ce1c6)