Validation Reference

kuml validate checks a .kuml.kts script for structural integrity and OCL constraint violations and reports all of them. It exits non-zero when any check fails, making it suitable as a blocking CI step.

Synopsis

kuml validate [options] <script>

kuml validate takes one script per invocation. To check several, call it once per file, for example in a shell loop.

Flag reference

Flag Default Effect

--strict

off

Fail on any expression parse warning (guards, effects, parametric constraints) in addition to OCL violations.

--check-stereotypes

off

Additionally validate stereotype applications: required properties and the OCL constraints a custom profile attaches (e.g. MustHaveIdAttribute). Without it, only element-level constraint(name, body) calls in the script are checked.

--no-check-structure

off

Skip structural checks (duplicate element IDs, circular inheritance, missing classifier references). Evaluate OCL constraints only. Useful when the structural issues are known and you only care about OCL correctness.

--no-check-style

off

Skip the named-argument source-style check (calls into dev.kuml.* with more than one value parameter must use named arguments).

-o, --output, --format

text

text or json. With json, all violations are written to stdout as a JSON array. Exit code semantics are unchanged. Useful for tooling integration (IDE plugins, custom reporters).

Exit codes

Code Meaning

0

All checks passed — no structural violations, no OCL violations.

2

Usage error — bad argument combination.

3

Script error — compilation failed, missing imports, or the script threw at build time.

4

I/O error — input file not found or unreadable.

5

Validation error — at least one structural or OCL violation found.

These codes are stable across kUML versions. CI scripts can branch on them.

Structural violation output

Structural checks run before OCL evaluation. They catch problems that would make OCL evaluation meaningless.

Example — duplicate element ID:

STRUCTURAL VIOLATION (duplicate-id)
  Element  : Class 'Order'
  Location : classDiagram("Domain") → classOf("Order")
  Message  : Duplicate element id 'Order' — another classifier with the same name exists
             in the same namespace.

Example — circular inheritance:

STRUCTURAL VIOLATION (circular-inheritance)
  Element  : Class 'A'
  Location : classDiagram("Cycle") → generalization(A → B → C → A)
  Message  : Circular generalisation detected: A → B → C → A

Note validation output

For SysML 2, BPMN and ERM scripts (and UML comments) kuml validate prints a Note validation: section and folds the findings into the structural part of the JSON output (category: "notes").

Code Severity Meaning

NOTE_TRUNCATED

warning

A note exceeds the display limit of 2000 characters / 30 lines and is rendered cut. The message names the note id and the limits, never the text.

SYSML2_NOTE_ANCHOR_UNKNOWN

error

A comment link points to an unknown comment or element.

SYSML2_NOTE_DUPLICATE_ID

error

A comment id collides with another element.

SYSML2_NOTE_NOT_SHOWN

warning

An unanchored comment is listed in no diagram.

BPMN_ASSOCIATION_UNKNOWN_REF

error

An association refers to an unknown annotation or element.

BPMN_ASSOCIATION_UNSUPPORTED_TARGET

warning

The target is a pool, lane or sequence flow; not rendered.

ERM_NOTE_ANCHOR_UNKNOWN

error

A note link refers to an unknown note or element.

ERM_NOTE_ANCHOR_UNSUPPORTED

error

The anchor is neither an entity nor a view.

kuml render prints the same findings as warnings on stderr and still renders.

OCL violation output

OCL violations appear after structural checks pass. Each violation prints:

  • The constraint name

  • The host classifier (the element that owns the constraint)

  • The OCL body

  • A short reason why evaluation returned false

Example:

OCL VIOLATION
  Constraint : PositiveTotal
  Host       : Class 'Order'
  Body       : self.total >= 0
  Reason     : Invariant evaluated to false for instance 'order42' (total = -5.00)

JSON output (--format json)

With --format json, all violations are written to stdout as a JSON array:

[
  {
    "kind": "structural",
    "code": "duplicate-id",
    "element": "Order",
    "location": "classDiagram(\"Domain\") → classOf(\"Order\")",
    "message": "Duplicate element id 'Order' ..."
  },
  {
    "kind": "ocl",
    "constraint": "PositiveTotal",
    "host": "Order",
    "body": "self.total >= 0",
    "reason": "Invariant evaluated to false ..."
  }
]

An empty array [] is written when all checks pass (exit code 0).

CI integration example

The following GitHub Actions step fails the build on any validation violation:

- name: Validate kUML models
  run: |
    for f in docs/architecture/domain.kuml.kts docs/architecture/services.kuml.kts; do
      kuml validate --strict "$f" || status=1
    done
    exit ${status:-0}

To capture structured output for a custom reporter:

- name: Validate and upload report
  run: |
    for f in src/**/*.kuml.kts; do
      kuml validate --format json "$f" || true
    done > kuml-violations.json
- name: Upload violation report
  uses: actions/upload-artifact@v4
  with:
    name: kuml-validation-report
    path: kuml-violations.json
Using || true prevents the step from failing so the artifact upload always runs. The next step or the overall job can be configured to fail on a non-empty violations file.

Relationship to OCL constraints in scripts

Constraints are declared inside classifier or stereotype blocks:

classDiagram("Domain") {
    val order = classOf("Order") {
        attribute("total", "BigDecimal")
        // Element-level constraint — evaluated by default
        constraint("PositiveTotal", body = "self.total >= 0")
    }
}

Profile-level constraints (in a KumlStereotype.constraints list) are only evaluated when --strict is passed. See Profiles for how to author stereotype constraints.

See also