Penstock

Guide / Checking

Every rule

One page for each check Penstock makes: why it matters and how to fix it.

Free

How to read a rule page

Every check Penstock makes has a page. It says why it matters, how to fix it, and where you see it. Select a finding in the Problems tab and its link opens the page. In penstock check --format json, SARIF and GitHub annotations, every finding carries the rule id and the address of its page.

LevelMeaning
ErrorThe diagram or the process is wrong. penstock check fails on it.
AdviceIt works, and reads or runs better without it. It is shown as a note and does not fail the check.
Off by defaultThe rule exists but does nothing until you turn it on.

152 rules in 8 groups: modelling rules, engine compatibility, drawing, process flow, decision tables, forms, diagrams and code, modelling conventions. The groups process flow, decision tables, diagrams and code, and modelling conventions are part of Pro. The rest is free.

Modelling rules

The bpmnlint rules that run on every BPMN diagram, in the editor and in penstock check. Which ones run, and how strictly, is set in .bpmnlintrc.

RuleWhatLevel
bpmnlint/ad-hoc-sub-processAd-hoc sub-process with a start or end eventError
bpmnlint/conditional-eventConditional event without a conditionOff by default
bpmnlint/conditional-flowsConditional flow without a conditionError
bpmnlint/end-event-requiredProcess or sub-process without an end eventError
bpmnlint/event-based-gatewayEvent-based gateway used wronglyError
bpmnlint/event-sub-process-typed-start-eventEvent sub-process start without an eventError
bpmnlint/fake-joinSeveral flows enter a task that does not join themAdvice
bpmnlint/globalGlobal element without a name, unused or not uniqueAdvice
bpmnlint/label-requiredElement without a labelError
bpmnlint/link-eventLink event without a name or without its counterpartError
bpmnlint/no-bpmndiElement without a place in the diagramError
bpmnlint/no-complex-gatewayComplex gatewayError
bpmnlint/no-disconnectedElement with no incoming or outgoing flowError
bpmnlint/no-duplicate-sequence-flowsTwo identical flows between the same elementsError
bpmnlint/no-gateway-join-forkGateway that joins and forksError
bpmnlint/no-implicit-endPath that ends without an end eventError
bpmnlint/no-implicit-splitTask that forks the flow without a gatewayError
bpmnlint/no-implicit-startPath that starts without a start eventError
bpmnlint/no-inclusive-gatewayInclusive gatewayAdvice
bpmnlint/no-overlapping-elementsElement overlaps another or leaves its parentAdvice
bpmnlint/single-blank-start-eventMore than one blank start eventError
bpmnlint/single-event-definitionEvent with several event definitionsError
bpmnlint/standard-sizeElement not in its standard sizeOff by default
bpmnlint/start-event-requiredProcess or sub-process without a start eventError
bpmnlint/sub-process-blank-start-eventSub-process start event with a typeError
bpmnlint/superfluous-gatewayGateway with one way in and one way outAdvice
bpmnlint/superfluous-labelLabel on a flow that needs noneAdvice
bpmnlint/superfluous-terminationTerminate end event that terminates nothingAdvice

Engine compatibility

What the engine the diagram is written for cannot run: a missing job type, an element or an expression the chosen version does not support. They run on Camunda 7 and Camunda 8 diagrams, in the editor and in penstock check, against the version in the file's modeler:executionPlatformVersion, or the newest one without it. Operaton and CIB seven are checked as Camunda 7. A finding is called compat/<rule> here and in penstock check; a rule is turned off in .bpmnlintrc as camunda-compat/<rule> or, the same, compat/<rule>.

RuleWhatLevel
compat/ad-hoc-sub-processAd-hoc sub-process without an activityError
compat/agent-fromai-contractfromAi() key that is not a plain name under toolCallError
compat/agent-tool-documentationTool of an AI agent without documentationAdvice
compat/agent-tool-output-keyTool of an AI agent that returns nothing to itAdvice
compat/before-all-execution-listenerbeforeAll listener outside a multi-instance elementError
compat/element-typeElement the engine version cannot runError
compat/cancel-execution-listenercancel listener on an element that cannot be cancelledError
compat/called-elementCall activity without a process to callError
compat/collapsed-subprocessCollapsed sub-processError
compat/connector-propertiesConnector with a property this version does not haveAdvice
compat/duplicate-execution-listener-headersTwo headers of a listener with the same keyError
compat/duplicate-execution-listenersTwo execution listeners that are the sameError
compat/duplicate-task-headersTwo task headers with the same keyError
compat/error-referenceError event without an error or an error codeError
compat/escalation-boundary-event-attached-to-refEscalation boundary event on the wrong elementError
compat/escalation-referenceEscalation event without an escalation or a codeError
compat/event-based-gateway-targetReceive task after an event-based gatewayError
compat/executable-processNo executable processError
compat/execution-listenerExecution listener without an event type or a job typeError
compat/feel-compatibilityFEEL function the engine version does not haveError
compat/feelFEEL expression that is not validError
compat/history-time-to-liveProcess without a history time to liveAdvice
compat/implementationTask or event that has nothing to runError
compat/inclusive-gatewayInclusive gateway with more than one way inError
compat/link-eventLink events that do not matchError
compat/loop-characteristicsMulti-instance without what it needsError
compat/io-mappingInput or output mapping that is incompleteError
compat/message-referenceMessage event without a message or its nameError
compat/no-binding-typeBinding type that this version does not haveError
compat/no-business-idBusiness id that this version does not haveError
compat/no-before-all-execution-listenerbeforeAll listener that this version does not haveError
compat/no-candidate-usersCandidate users that this version does not haveError
compat/no-cancel-execution-listenercancel listener that this version does not haveError
compat/no-execution-listener-headersListener headers that this version does not haveError
compat/no-execution-listenersExecution listeners that this version does not haveError
compat/no-expressionExpression this version does not supportError
compat/no-interrupting-event-subprocessInterrupting event sub-process in an ad-hoc sub-processError
compat/no-job-priority-definitionJob priority that this version does not haveError
compat/no-loopLoop that never waitsError
compat/no-multiple-none-start-eventsMore than one blank start event in Camunda 8Error
compat/no-priority-definitionPriority that this version does not haveError
compat/no-propagate-all-parent-variablesPropagate all parent variables that this version does not haveError
compat/no-signal-event-sub-processSignal event sub-process that this version does not haveError
compat/no-task-scheduleTask schedule that this version does not haveError
compat/no-task-listenersTask listeners that this version does not haveError
compat/no-templateElement template that this version does not haveError
compat/no-version-tagVersion tag that this version does not haveError
compat/no-zeebe-propertiesZeebe properties that this version does not haveError
compat/no-zeebe-user-taskCamunda user task that this version does not haveError
compat/priority-definitionUser task priority that is not validError
compat/zeebe-user-taskJob worker user taskAdvice
compat/secretsSecret written in a form the engine no longer readsAdvice
compat/sequence-flow-conditionCondition on a flow that cannot have oneError
compat/signal-referenceSignal event without a signal or its nameError
compat/start-event-formStart event form that this version cannot showError
compat/start-event-form-embeddedEmbedded form on a start eventAdvice
compat/subscriptionMessage without a correlation keyError
compat/task-listenerTask listener without an event type or a job typeError
compat/task-scheduleTask schedule that is not a dateError
compat/timerTimer that is not validError
compat/unresolvable-secret-referenceSecret used in a way the engine cannot resolveError
compat/user-task-definitionUser task without a formAdvice
compat/user-task-formUser task form that is not filled inError
compat/variable-nameVariable name that is not validError
compat/version-tagVersion tag that is emptyError
compat/wait-for-completionCompensation that does not waitError

Drawing

What is wrong with how a diagram is drawn, found by the check card in the editor and by the first section of penstock check. The errors break the picture; the others make it harder to read.

RuleWhatLevel
drawing/dangling-connectionConnection without both endsError
drawing/lost-connectionConnection in the file but not on the canvasError
drawing/containmentElement outside the container it belongs toError
drawing/overlapShapes sit on top of each otherError
drawing/edge-through-nodeConnection runs through a shapeError
drawing/edge-through-boundaryConnection runs through a boundary eventError
drawing/crossingConnections crossAdvice
drawing/detached-edgeConnection does not reach the shape it connectsError
drawing/boundary-off-hostBoundary event is off its hostError
drawing/label-adriftLabel sits far from what it namesAdvice
drawing/diagonal-edgeConnection is not drawn at right anglesAdvice
drawing/label-overlapLabels cover each otherError
drawing/merged-edgeConnections run along the same lineAdvice
drawing/note-adriftAnnotation sits far from what it describesAdvice
drawing/semantic-driftThe diagram means something differentError
drawing/backtrackConnection doubles back along itselfError
drawing/edge-through-labelConnection crosses a labelAdvice
drawing/edge-along-shapeConnection runs along the border of a shapeAdvice
drawing/detourConnection takes a long way roundAdvice
drawing/jogConnection sidesteps for no reasonAdvice

Process flow

What the way a process is wired can do when it runs. Part of Penstock Pro, and Team in a pipeline.

RuleWhatLevel
flow/deadlockThe process can get stuckError
flow/no-synchronizationA part of the process can run twiceError
flow/dead-elementAn element can never runError
flow/never-finishesThe process may never finishError
flow/too-complexOnly part of the process was analysedAdvice
flow/no-way-outA decision has no way out for some valuesError
flow/overlapTwo ways out of a decision can both holdError
flow/no-defaultA decision may have no way outAdvice
flow/lookalikeTwo variables look like oneAdvice

Decision tables

What a DMN decision table does with the inputs it can be given. Part of Penstock Pro, and Team in a pipeline.

RuleWhatLevel
table/rule-overlapTwo rules match the same inputError
table/rule-gapNo rule matches some inputAdvice
table/table-unreadA decision table could not be checkedAdvice

Forms

What a Camunda Form does with what the user enters. The form check is lint, so it is free.

RuleWhatLevel
form/key-clashTwo fields write the same variableError
form/no-keyA field writes no variableError
form/repeated-optionAn option list repeats a valueError
form/no-labelA field has no labelAdvice

Diagrams and code

Where a diagram and the code that runs it disagree: a step nothing implements, a worker no diagram uses, a variable read under another name than it is set.

RuleWhatLevel
code/missing-implementationNothing in the code runs a stepAdvice
code/never-thrownNothing in the code throws the error a step catchesAdvice
code/variable-typoA variable is read, but only a similar one is setAdvice
code/worker-fetchA worker reads a variable it does not fetchAdvice
code/writer-unreadA worker sets a variable no step after it readsAdvice
code/lost-updateEvery parallel instance writes the same result collectionAdvice
code/late-readA worker reads a variable no step before it setsAdvice
code/near-nameA job type, topic, bean, message or error code is one letter off the codeAdvice
code/mapping-orderA mapping line reads a value an earlier line was meant to setAdvice
code/implicit-job-typeA job worker takes its job type from the method nameAdvice
code/no-workerNo worker handles a job typeError
code/no-topic-workerNo external task worker subscribes to a topicError
code/class-missingA class named in the diagram is not in the projectError
code/bean-missingNo Spring bean has the name a diagram usesError
code/unknown-processA call activity calls a process no diagram definesError
code/unknown-decisionA business rule task calls a decision no file definesError
code/unknown-formA user task shows a form no file definesError
code/unknown-embedded-formA user task shows an embedded form the diagram does not containError
code/unused-workerA worker for a job type no diagram usesAdvice
code/unused-subscriptionA subscription to a topic no diagram usesAdvice

Modelling conventions

Conventions the editor applies while modelling, so a team does not have to remember them. They are set under conventions in penstock.yaml.

RuleWhatLevel
convention/id-from-nameIds follow namesOff by default
convention/defaultsDefaults for new elementsOff by default