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
- 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)
- Set the extra source first via PUT /repository/models/{modelId}/source-extra with a multipart file, then re-fetch
- If the extra source is genuinely absent, handle 404 on the client instead of treating it as fatal
- 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
- Always call addModelEditorSourceExtra when saving models intended to expose extra source
- Check GET /repository/models/{modelId} before fetching source endpoints
- Treat source/source-extra as optional in client code
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
- Model with id ' ' does not have source available.
- A group or a user is required to create an identity link.
- A group or a user is required to create an identity link.
- Authentication failed for this username and password
- Cannot find bpmn model for process definition id
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)