Home / Docs / CLI / casen check

casen check

Check .bpmn, .dmn and .form files in one call — BPMN lint, DMN and form validation and the references between them, each finding with a rule id, element id and a concrete fix.

casen check is the gate to run before you deploy, or after every edit in an agent loop. It takes any mix of BPMN, DMN and form files and checks each one, then the references between them. It exits non-zero when there is an error.

casen check order.bpmn review.form discount.dmn
order.bpmn
  ⚠ check/unresolved-form [ReviewOrder] "ReviewOrder" links formId "review", which none of the checked forms has.
      fix: Set formId to one of "review-form", or check the form that has id "review" too.
discount.dmn
  ✖ dmn/feel-syntax [InputEntry_3] Input entry of rule "Rule_2" is not valid FEEL unary tests: Unexpected token '<' (at 9) in `>= 10 and < 20`.
      fix: Write unary tests: a value ("gold", 42), a comparison (> 10), a range ([1..5]), a list ("a","b"), not(...), or - for any.

2 findings: 1 error, 1 warning

Options

OptionDescription
--deployDeploy-readiness gate. Camunda 8 rules run even on a model that names no platform, user tasks need a form, and cross-file references are errors. Only errors are shown.
--sketchSketch profile. Skips every Camunda 8 deployability rule on BPMN files.
--user-task-forms require|offReport user tasks that have no form, or not. Default: require with --deploy, off otherwise.
--jsonPrint { ok, errors, warnings, findings }.
--no-bpmnlintrcIgnore the project’s .bpmnlintrc.

Each finding has the same fields for every file kind:

{
  "file": "discount.dmn",
  "kind": "dmn",
  "rule": "dmn/unresolved-requirement",
  "severity": "error",
  "elementId": "Decision_discount",
  "message": "<requiredDecision href=\"#tier\"> on \"Decision_discount\" points at a <inputData>, not a <decision>.",
  "fix": "Use <requiredInput> for input data."
}

Profiles

ProfileUse it whenWhat runs
defaultYou edit a model that targets Camunda 8Every rule. Camunda 8 rules run only when the model names a platform (modeler:executionPlatform). A user task without a form is not reported.
--sketchYou draw a process before it targets an engineStructure, flow, naming, FEEL syntax. No deploy/, compat/, connector/ or agentic/ rules, even if the model names a platform.
--deployYou are about to deployEvery rule, errors only. A user task without a form is an error (compat/user-task-definition); --user-task-forms off turns it off. Outside --deploy, --user-task-forms require reports it as a warning. A formId or decisionId that none of the checked files defines is an error.

Zeebe deploys a user task that has no form. So outside the deploy gate the “user task needs a form” rule is off: it would push you to invent a form reference only to clear a warning. Turn it on with --user-task-forms require. casen lint lint has the same --profile sketch|deploy and --user-task-forms options.

What is checked

BPMN — the XML is well-formed, then every casen lint rule runs (a project .bpmnlintrc is honoured).

DMN

RuleSeverityWhat it means
dmn/malformed-xmlerrorThe XML does not parse
dmn/not-dmnerrorThe root is not <definitions>
dmn/duplicate-iderrorTwo elements share an id
dmn/missing-iderrorA decision, input data, BKM or knowledge source has no id
dmn/no-decisionerrorThe document has no decision
dmn/unresolved-requirementerrorA requiredDecision, requiredInput, requiredKnowledge or requiredAuthority href points at nothing, or at the wrong kind of element
dmn/requirement-cycleerrorDecisions require each other in a cycle
dmn/decision-no-logicerrorA decision has no decision table and no literal expression
dmn/empty-expressionerrorA literal expression is empty
dmn/invalid-hit-policyerrorThe hit policy is not a DMN hit policy
dmn/invalid-aggregationerrorAn unknown aggregation, or an aggregation without COLLECT
dmn/no-outputerrorA decision table has no output
dmn/missing-output-nameerrorA table with several outputs has an output with no name
dmn/empty-input-expressionerrorAn input column has no expression
dmn/rule-entry-counterrorA rule’s entries do not match the table’s columns
dmn/feel-syntaxerrorAn input expression, input entry (unary tests), output entry or literal expression is not valid FEEL
dmn/invalid-type-refwarningA typeRef is not a DMN/FEEL type

Forms (form-js JSON)

RuleSeverityWhat it means
form/invalid-jsonerrorThe file is not JSON
form/invalid-schemaerrorNot { id, type: "default", components: [] }, a component with no type, or a bad button action
form/missing-iderrorThe form or a component has no id
form/duplicate-iderrorTwo components share an id
form/missing-keyerrorAn input field is bound to no variable
form/invalid-keyerrorA key is not a variable name or dotted path
form/duplicate-keyerrorTwo fields bind the same key in the same data scope
form/missing-optionserrorA select, radio, checklist or taglist has no options
form/missing-expressionerrorAn expression field has no expression
form/feel-syntaxerrorA property starting with = (a condition, an expression, a label) is not valid FEEL
form/invalid-validationerrorA validate.pattern is not a regular expression, or min is above max
form/conditional-not-feelwarningconditional.hide has no leading =, so it is not evaluated
form/unknown-typewarningA component type form-js does not provide

Between files — checked only when at least one file of the referenced kind is given:

RuleSeverityWhat it means
check/unresolved-formwarning, error with --deployA user task’s formId is not the id of a checked form
check/unresolved-decisionwarning, error with --deployA business rule task’s decisionId is not a decision in a checked DMN file

The same checks are in @bpmnkit/core as lintDmn(xml) and lintForm(json).