flowable/flowable-engine · error · FlowableObjectNotFoundException

Could not find an app deployment with id '<deploymentId>

Error message

Could not find an app deployment with id '<deploymentId>

What it means

Thrown by AppDeploymentResource.getAppDeployment when no app deployment with the given deploymentId exists in the app engine repository: the deployment query returns null. Flowable signals this with FlowableObjectNotFoundException so REST clients get a not-found outcome rather than a null dereference.

Source

Thrown at modules/flowable-app-engine-rest/src/main/java/org/flowable/app/rest/service/api/repository/AppDeploymentResource.java:61

    protected AppRestResponseFactory appRestResponseFactory;

    @Autowired
    protected AppRepositoryService appRepositoryService;
    
    @Autowired(required=false)
    protected AppRestApiInterceptor restApiInterceptor;

    @ApiOperation(value = "Get an app deployment", tags = { "App Deployments" })
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Indicates the app deployment was found and returned."),
            @ApiResponse(code = 404, message = "Indicates the requested app deployment was not found.")
    })
    @GetMapping(value = "/app-repository/deployments/{deploymentId}", produces = "application/json")
    public AppDeploymentResponse getAppDeployment(@ApiParam(name = "deploymentId") @PathVariable String deploymentId) {
        AppDeployment deployment = appRepositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();

        if (deployment == null) {
            throw new FlowableObjectNotFoundException("Could not find an app deployment with id '" + deploymentId);
        }
        
        if (restApiInterceptor != null) {
            restApiInterceptor.accessDeploymentById(deployment);
        }

        return appRestResponseFactory.createAppDeploymentResponse(deployment);
    }

    @ApiOperation(value = "Delete an app deployment", tags = { "App Deployments" }, code = 204)
    @ApiResponses(value = {
            @ApiResponse(code = 204, message = "Indicates the App deployment was found and has been deleted. Response-body is intentionally empty."),
            @ApiResponse(code = 404, message = "Indicates the requested app deployment was not found.")
    })
    @DeleteMapping(value = "/app-repository/deployments/{deploymentId}", produces = "application/json")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void deleteAppDeployment(@ApiParam(name = "deploymentId") @PathVariable String deploymentId) {
        AppDeployment deployment = appRepositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. List valid deployments via GET /app-repository/deployments and use an id from the response.
  2. Verify the REST app's datasource points at the database where the deployment was made.
  3. Catch FlowableObjectNotFoundException and map it to HTTP 404 in your client.
  4. Check whether the deployment was deleted (deleteAppDeployment) or purged by housekeeping.

Example fix

// before
AppDeploymentResponse d = restTemplate.getForObject("/app-repository/deployments/" + id, AppDeploymentResponse.class);
// after
try {
    AppDeploymentResponse d = restTemplate.getForObject("/app-repository/deployments/" + id, AppDeploymentResponse.class);
} catch (HttpClientErrorException.NotFound e) {
    // handle unknown deployment id
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Confirm the deployment exists before fetching details
ResponseEntity<List<AppDeploymentResponse>> list = restTemplate.exchange(
  "/app-repository/deployments", HttpMethod.GET, null,
  new ParameterizedTypeReference<List<AppDeploymentResponse>>() {});
boolean known = list.getBody().stream().anyMatch(d -> d.getId().equals(deploymentId));

Try / catch

try {
    return restTemplate.getForObject("/app-repository/deployments/" + id, AppDeploymentResponse.class);
} catch (HttpClientErrorException.NotFound e) {
    return Optional.empty(); // deployment does not exist
}

Prevention

When it happens

Trigger: GET /app-repository/deployments/{deploymentId} with an id that was never deployed, was deleted, or belongs to a different engine/database than the one this REST app is configured against.

Common situations: Stale ids cached in clients after cleanup; pointing at the wrong database schema or tenant; case-mismatched ids; environment drift between dev and prod deployments.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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