flowable/flowable-engine · error · FlowableObjectNotFoundException

Model with id ' ' does not have extra source available.

Error message

Model with id '${modelId}' does not have extra source available.

What it means

Thrown by the Flowable REST API when GET /repository/models/{modelId}/source-extra is called for a model that exists but has no extra editor source bytes stored. Flowable stores the 'extra' editor source separately from the model itself; repositoryService.getModelEditorSourceExtra returns null and the resource raises FlowableObjectNotFoundException.

Solutions

  1. Verify the model id is correct and that the intended model actually has extra source (GET /repository/models/{modelId} and check the model in ACT_RE_MODEL)
  2. Set the extra source first via PUT /repository/models/{modelId}/source-extra with a multipart file, then re-fetch
  3. If the extra source is genuinely absent, handle 404 on the client instead of treating it as fatal
  4. If the model should have extra source but does not, re-save it from the source of truth (designer/import)

Example fix

// before
curl -X GET http://localhost:8080/flowable-rest/repository/models/myModelId/source-extra
// after
curl -X PUT -F 'file=@extra-source.xml' http://localhost:8080/flowable-rest/repository/models/myModelId/source-extra
curl -X GET http://localhost:8080/flowable-rest/repository/models/myModelId/source-extra
Defensive patterns

Strategy: try-catch

Validate before calling

Model m = repositoryService.createModelQuery().modelId(modelId).singleResult();
boolean hasExtra = m != null && repositoryService.getModelEditorSourceExtra(m.getId()) != null;
if (!hasExtra) throw new IllegalStateException("model has no extra source");

Try / catch

try { byte[] b = getModelBytes(modelId); } catch (FlowableObjectNotFoundException e) { /* model exists but no extra source; use default */ }

Prevention

When it happens

Trigger: GET /repository/models/{modelId}/source-extra on a model that was created or saved without ever calling addModelEditorSourceExtra (e.g. a model created via the REST API or designer that only has base source or no source at all).

Common situations: Deploying models programmatically without setting extra source; copying a model and forgetting to copy the extra source; clients assuming source-extra exists whenever source exists; upgrading Flowable where legacy models were imported without extra source.

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/955314f0aa4e346a. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/repository/ModelSourceExtraResource.java:59

/**
 * @author Frederik Heremans
 */
@RestController
@Api(tags = { "Models" }, authorizations = { @Authorization(value = "basicAuth") })
public class ModelSourceExtraResource extends BaseModelSourceResource {

    @ApiOperation(value = "Get the extra editor source for a model", tags = { "Models" }, nickname = "getExtraEditorSource",
            notes = "Response body contains the model’s raw editor source. The response’s content-type is set to application/octet-stream, regardless of the content of the source.")
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Indicates the model was found and source is returned."),
            @ApiResponse(code = 404, message = "Indicates the requested model was not found.")
    })
    @GetMapping("/repository/models/{modelId}/source-extra")
    public byte[] getModelBytes(@ApiParam(name = "modelId") @PathVariable String modelId, HttpServletResponse response) {
        Model model = getModelFromRequest(modelId);
        byte[] editorSource = repositoryService.getModelEditorSourceExtra(model.getId());
        if (editorSource == null) {
            throw new FlowableObjectNotFoundException("Model with id '" + modelId + "' does not have extra source available.", String.class);
        }
        response.setContentType("application/octet-stream");
        return editorSource;
    }

    @ApiOperation(value = "Set the extra editor source for a model", tags = { "Models" }, nickname = "setExtraEditorSource", consumes = "multipart/form-data",
            notes = "Response body contains the model’s raw editor source. The response’s content-type is set to application/octet-stream, regardless of the content of the source.",
            code = 204)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", dataType = "file", paramType = "form", required = true)
    })
    @ApiResponses(value = {
            @ApiResponse(code = 204, message = "Indicates the model was found and the extra source has been updated."),
            @ApiResponse(code = 404, message = "Indicates the requested model was not found.")
    })
    @PutMapping(value = "/repository/models/{modelId}/source-extra", consumes = "multipart/form-data")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void setModelSource(@ApiParam(name = "modelId") @PathVariable String modelId, HttpServletRequest request) {

View on GitHub (pinned to d6d39ce1c6)