Diagnostics
Every conformance diagnostic carries a stable code of the form
DSL-<severity>-<area>-<number>. Search for the code — that is what it is for.
| Severity | Meaning |
|---|---|
E | Error. The document is rejected. |
W | Warning. Printed, and suppressible per code. |
I | Info. Printed only with --style. |
--strict promotes every warning to an error, which is what you want in CI. A
model can also escalate specific codes itself through
documentation.options.lint.error, or silence them through
documentation.options.lint.silence — see
Conformance flags.
Codes are added as rules are implemented. If you meet a code that is not here, it is a bug in this page — please tell us. A CI check keeps the two in step, so it should not happen.
Engineering units
Units are validated against UNECE Recommendation 20, the same list the
find_engineering_unit tool searches.
DSL-E-UNIT-001 — unknown unit
The symbol is not a UNECE Rec. 20 unit. The message suggests the closest known one.
engineeringUnits: "degree Celsius" # ✗ prose, not a symbol
engineeringUnits: "°C" # ✓
This is an error: an unknown unit would be written into the NodeSet2 as a unit no client can interpret.
DSL-W-UNIT-002 — ambiguous symbol
Several UNECE units share the symbol you wrote — V, MW and r/min are all
ambiguous. The compiler resolves to the first deterministically and tells you
which; the message lists the long names so you can be explicit.
DSL-W-UNIT-003 — near match
Not an exact symbol, but close enough to one that the compiler will use it. Write the exact symbol to silence this.
DSL-W-UNIT-004 — US spelling
You wrote a US spelling (meter); UNECE uses the international one (metre).
The compiler uses the UNECE spelling.
Devices (DI)
The Devices companion specification (OPC 10000-100) is prescriptive about where things
live: process values and methods on a di:ComponentType subtype, the nodes a FunctionalGroup
organizes, the Devices in DeviceSet, the Networks in NetworkSet. These run only on a model
that imports DI (the DI extension, ADR-010), and DSL-W-DI-001 is the most common finding in a
first model. Each cites the sentence of OPC 10000-100 v1.05 it enforces: a "shall" is an error,
a "should" a warning.
DSL-W-DI-001 — process value outside ParameterSet
OPC 10000-100 (DI) v1.04 §4.3 — "the Parameters are components of the ParameterSet as a flat list of Parameters."
A Variable is declared directly on the type instead of inside the overridden
di:ParameterSet.
- browseName: MySensorType
subtypeOf: di:ComponentType
components:
- browseName: Temperature # ✗ top-level process value
dataType: ua:Double
- browseName: MySensorType
subtypeOf: di:ComponentType
components:
- browseName: di:ParameterSet # ✓ redeclared, making it mandatory
components:
- browseName: Temperature
dataType: ua:Double
di:ParameterSet is optional on the base type; redeclaring it here is what
makes it mandatory on every instance.
DSL-W-DI-002 — method outside MethodSet
The same rule for Methods: on a di:ComponentType subtype they belong inside
the overridden di:MethodSet, not at the type's top level.
DSL-E-DI-003 — a FunctionalGroup organizes two nodes with the same name
OPC 10000-100 §4.4.1 — "All BrowseNames for Nodes referenced by a FunctionalGroup with an Organizes Reference shall be unique."
A client finds an element of a FunctionalGroup by its BrowseName: two Speed variables, one
from ParameterSet and one from elsewhere, make that ambiguous. Organize one of them only.
DSL-W-DI-005 — a FunctionalGroup organizes a node of another element
OPC 10000-100 §4.4.1 — "Organizes References should be used when the elements are components in other parts of the TopologyElement that the FunctionalGroup belongs to."
The group organizes a node that is not part of the Device (TopologyElement) it belongs to, for instance a parameter of another Device.
DSL-W-DI-006 — a Device that DeviceSet does not reach
OPC 10000-100 §4.9 — DeviceSet "shall either directly or indirectly reference all instances of a subtype of ComponentType with a Hierarchical Reference."
DI clients find Devices from DeviceSet: place the instance with
organizedBy: /ua:Objects/di:DeviceSet, or under a Device that is there. A warning, not an
error, because some companion specifications place their components under folders of their own.
DSL-E-DI-007 — a component of a composed Device is in DeviceSet too
OPC 10000-100 §4.9 — "only the root instance shall be referenced from the DeviceSet Object."
A Device that is a component of another Device is reached through it; referencing it from
DeviceSet as well lists it twice.
DSL-E-DI-008 — a Network outside NetworkSet
OPC 10000-100 §5.6 — "All Networks shall be components of the NetworkSet Object."
Declare the Network with componentOf: /ua:Objects/di:NetworkSet.
DSL-E-DI-009 — a ConnectionPoint no Device holds
OPC 10000-100 §5.4 — "the ConnectionPoints shall have the inverse Reference (ComponentOf) to the Device."
A ConnectionPoint is how a Network reaches a Device: declare it as a component of the Device.
DSL-E-DI-010 — a Lock no owner holds
OPC 10000-100 §7.3 — "It shall be referenced using HasComponent or HasAddIn from the lock-owner Object."
A di:LockingServicesType Object belongs to what it locks, usually a Device: declare it as a
component (or an AddIn) of that Device.
DSL-E-DI-101 — a di: block with a key it does not know
A di: block holds exactly one kind, device, component, block or topologyElement,
and each takes parameters, methods, groups, identification, nameplate and lock
(see the DI vocabulary). On an instance it takes
only values, nameplate and parameters, and the instance names its typeDefinition.
DSL-E-DI-102 — a di: group member that names nothing
A member of a group, or of identification, is a parameter or a method of the same block, or a
nameplate Property (Manufacturer, SerialNumber, …). Another element of the type is written
as a path: /Range.
DSL-E-DI-103 — a nameplate name the block cannot make Mandatory
nameplate: lists Optional nameplate Properties of DI to make Mandatory. On a device, the
eight of OPC 10000-100 §4.7 (SerialNumber, Manufacturer, Model, …) are Mandatory already.
Naming
DSL-E-NAMING-001 — a browse name that is not an identifier
OPC UA Part 3 v1.05 §6.4.4.4.4 recommends angle brackets on a placeholder
A browse name chosen by the model must be letters, digits and underscores,
starting with a letter; a placeholder is written <Name>, alone or inside a
name. OPC UA itself accepts any string, but a name with spaces, slashes or #
cannot be written in a browse path, a generated symbol or most client code.
- browseName: <User defined Input#> # ✗
- browseName: <UserDefinedInput> # ✓
- browseName: Port<n> # ✓ a numbered member
A name with a namespace prefix (di:Manufacturer, ua:<OrderedObject>) belongs
to another specification and is not checked. When a published NodeSet is
projected as it is (tolerant mode, spec-repo pull), the finding is a warning,
written as a comment above its line.
DSL-W-NAMING-003 — type browse name without the Type suffix
Model-Best v1.03 §2.1.3 — "The BrowseName of a TypeDefinitionNode should have the suffix
Type."
An ObjectType or VariableType whose browse name does not end in Type. The
suffix is what lets a reader tell a type from an instance at a glance, and it is
near-universal in the published companion specifications.
SomeObject → SomeObjectType. Interface types are not exempt: the convention
there is I…Type, as in IVendorNameplateType.
DSL-W-NAMING-005 — Structure DataType suffix
Model-Best v1.03 §2.1.3 — "For Structured DataTypes (subtypes of the Structure DataType) the suffix should be
DataType."
ThreeDVector should be ThreeDVectorDataType.
Structure
DSL-W-STRUCT-006 — AddIn without a default browse name
OPC UA Part 3 v1.05 §4.10.3 — "The AddIn ObjectType shall include the definition of a default BrowseName using the DefaultInstanceBrowseName Property."
An AddIn ObjectType should declare DefaultInstanceBrowseName so instances can
adopt it rather than each inventing a name.
Raised only when the add-in type belongs to your model, where you can fix it.
Attaching a type from another namespace that you cannot change — ua:FolderType,
as OPC 40001-1 Machinery does for MachineryBuildingBlocks — with an explicit
browseName: is reported as information instead.
DSL-W-STRUCT-009 — inherited member restated
OPC UA Part 3 v1.05 §6.4.4
A member inherited from the parent's typeDefinition restates its nodeClass
or its typeDefinition identically. It adds nothing and is ignored — only a
redeclaration that changes something has an effect.
Remove the line. If you meant to narrow the type, give a typeDefinition that
is a subtype of the inherited one.
DSL-E-STRUCT-010 — inherited member contradicted
OPC UA Part 3 v1.05 §6.4.4
A subtype may refine an inherited member, not contradict it. This is raised when the redeclaration changes:
- the
nodeClass— it is fixed by the declaration you inherit from; - the
typeDefinitionto something that is not a subtype of the inherited one; - a Mandatory member's modelling rule to something weaker.
Remove the conflicting key, or make the typeDefinition a subtype of the one
you inherit.
DSL-W-STRUCT-011 — browse path does not resolve
OPC UA Part 4 v1.05 §5.8.4
A browse path could not be followed from its starting node — one of its steps matches nothing.
The usual cause is an Optional member that was never activated: an optional
member only exists once something asks for it, so a path through one that was
not listed in optionals: has nothing to traverse. Check each step of the path,
and that every optional step on it is actually materialised.
DSL-W-STRUCT-012 — modellingRule where there is nothing to govern
OPC UA Part 3 v1.05 §6.4.4
modellingRule on a node whose parent is not an ObjectType or VariableType. A
ModellingRule governs an InstanceDeclaration, which only exists under a type;
on a member of an ordinary Object or Variable there is none, so the key is
ignored.
Remove it — or move the member under the type, if it was meant to be part of the type's definition.
DSL-E-STRUCT-013 — a Method that nothing owns
OPC UA Part 3 v1.05 §5.7.1
A Method declared under organizes:. A Method shall be the target of at least
one HasComponent from an Object or ObjectType; a folder may organize a Method,
but only one that some node owns. Declare it where it belongs, and organize it
with a reference:
objectTypes:
- browseName: MyControlFunctionType
components:
- browseName: Operational
typeDefinition: di:FunctionalGroupType
organizes:
- browseName: Stop # ✗ a Method with no owner
nodeClass: Method
references: # ✓ the state machine's own Stop
- referenceType: ua:Organizes
source: /Operational
target: /ControlFunctionState/Stop
The target must exist in the type: a method the state machine only inherits
from its own type is not a node of this one, so redeclare it (under the state
machine member's methods:) before organizing it.
The reverse writes this form only when the NodeSet itself declares such a
Method, as OPC 30500 LADS 1.0.0 does for six of them: the finding is then about
the published NodeSet. When such a NodeSet is projected as it is (tolerant mode,
spec-repo pull), the finding is a warning, written as a comment above its line,
and the Method is built as a component of the folder.
DSL-W-STRUCT-014 — an instance with no parent
OPC UA Part 3 v1.05 §5.2.1
An instances: entry with none of organizedBy, componentOf or propertyOf.
It is built as declared, but no hierarchical reference reaches it: a client
browsing from the Objects folder never finds it. Give it a parent:
instances:
- browseName: Configuration
typeDefinition: di:FunctionalGroupType
organizedBy: /ua:Objects # ✓ reachable
The reverse writes this form only when the NodeSet declares such a node, as OPC 10000-100 DI does for its design-tool FunctionalGroups (Configuration, Tuning, …): leaving it out would renumber it, and its NodeId is part of the companion specification.
DSL-W-NS-005 — member shadows an inherited one
OPC UA Part 3 v1.05 §4.1
A declared member has the same name as an inherited member but a different namespace, so both exist side by side. A BrowseName is qualified by its namespace, which makes this legal — and easy to miss, because the two read identically unless you look at the prefix.
If you meant to refine the inherited member, use its namespace prefix. If you meant a genuinely new member, a distinct name will save the next reader.
DSL-W-STRUCT-007 — Property reachable only through a Folder
OPC UA Part 3 v1.05 §4.4.2 — "Properties are defined using the HasProperty Reference."
A Property is reachable only by an Organizes reference from a Folder, with no
HasProperty from the Node it belongs to. A Folder may organize a Property it
does not own, but the owning Node still has to declare it — otherwise a client
browsing the Node never sees the Property.
DSL-W-STRUCT-008 — optionals: on a type
OPC UA Part 3 v1.05 §6.4.4
optionals: on a type has no effect and was discarded. A type's members are
inherited from its supertype already carrying their own modelling rule;
optionals: only means something where a typeDefinition is instantiated. To
make an inherited member Mandatory on a type, use promotedToMandatory:.
Reference types
DSL-E-DT-009 — dataType where typeDefinition belongs
OPC UA Part 3 v1.05 §4.4
dataType: names something that resolves to an ObjectType. A Variable has a
DataType; an Object has a TypeDefinition. These are the two being confused, and
the node would end up with neither.
components:
- browseName: MyComponent
dataType: MyObjectType # ✗
typeDefinition: MyObjectType # ✓
DSL-W-REF-004 — inverseName omitted
OPC UA Part 3 v1.05 §5.3.3
An asymmetric ReferenceType named Has<X> declared no inverseName, so Is<X>Of
was derived and used. The model still builds, but the generated NodeSet carries a
name nobody chose — write it explicitly if the derived one is not what you mean.
DSL-W-REF-003 — inverseName differs from the convention
OPC UA Part 3 v1.05 §5.3.3
A Has<X> ReferenceType whose inverseName is neither <X>Of nor Is<X>Of. The
standard uses both: <X>Of for its core references (HasComponent / ComponentOf,
HasProperty / PropertyOf, HasSubtype / SubtypeOf) and Is<X>Of for others
(HasCondition / IsConditionOf). Another name makes the relationship read as
something other than it is. Deliberate departures are fine — this is a warning, not an
error (HasCause / MayBeCausedBy is one the standard makes itself).
Keys and lists
These are about the modelling language itself rather than OPC UA. Each one catches something that would otherwise be skipped without a word, leaving a model that builds but is not the one you wrote.
DSL-E-KEY-001 — unknown key on a member or an entry
A component, property, method or other member, or an entry of a section such
as objectTypes: or instances:, carries a key it does not accept. The key is
never read, so whatever it was meant to set keeps its default:
components:
- browseName: Pressure
dataType: ua:Double
modelingRule: Optional # ✗ one L — the member stays Mandatory
modellingRule: Optional # ✓
objectTypes:
- browseName: PressBaseType
isAbstact: true # ✗ one R missing — the type stays concrete
isAbstract: true # ✓
When the key is close to a real one the message names it
(do you mean modellingRule instead ?). When nothing is close it says so rather
than guess. An objects: entry is created as written, so an instance key such
as dataType or optionals is reported there with a pointer to instances:.
An ObjectType or VariableType entry with a nested subtypes: list gets the same
error. A subtype is always its own entry naming its parent with subtypeOf:
objectTypes:
- browseName: MachineType
- browseName: MillType
subtypeOf: MachineType # ✓ not `subtypes:` under MachineType
DSL-W-KEY-002 — unknown top-level key
A key at the root of the document that the model does not define, most often a
misspelt section name such as objectType:. Nothing reads it, so every entry
under it is missing from the generated NodeSet. It is a warning because a stray
key is harmless in itself; under --strict it is an error.
DSL-E-KEY-003 — a list was expected
A section (objectTypes, dataTypes, instances, …) or a member list
(components, properties, methods, …) is a mapping or a single value. Each
holds a YAML list, one item per node, named by its browseName:
objectTypes:
HydraulicPressType: # ✗ keyed by name: none of it is read
subtypeOf: di:DeviceType
objectTypes:
- browseName: HydraulicPressType # ✓
subtypeOf: di:DeviceType
Until this diagnostic existed the first form produced no output and no message: a model written that way validated as correct while defining nothing.
Organizes links
A string under organizes: links a node declared elsewhere (see
Organizes links). Inside a type,
$Name names the member of that type whose BrowseName is Name.
DSL-E-LINK-001 — $Name matches several members
Two or more members of the type carry that BrowseName, at different depths, so
the link would be a guess. The message lists each one with its path from the
type. Write the path of the one you mean, or give it an $anchor:
- browseName: Limits
typeDefinition: ua:FolderType
organizes: [$Speed] # ✗ Axis1/Speed or Axis2/Speed?
organizes: [/Axis2/Speed] # ✓ the path from the type
organizes: [$Axis2Speed] # ✓ with `$anchor: Axis2Speed` on that member
DSL-E-LINK-002 — $Name matches no member
No member of the type, declared or inherited, has that BrowseName: usually a typo. Members with a close name are suggested, with their paths. No reference is made.
DSL-E-PERM-001 — role not found
The role: of a rolePermissions: entry is not a RoleType instance. A short
name is looked up among roles only, in the namespace its prefix names; a leading
/ takes a full browse path instead:
rolePermissions:
- role: ua:Operater # ✗ no role has that name; the message lists the ones that exist
permissions: [Browse]
- role: ua:Operator # ✓ an ns0 role, by its BrowseName
permissions: [Browse, Read]
- role: MaintenanceRole # ✓ a role this model declares
permissions: [Browse, Call]
Use the BrowseName (ua:Operator), not the SymbolicName WellKnownRole_Operator.
The entry is left out, so the node grants that role nothing.
DSL-E-PERM-002 — not a permission name
A permissions: name that is not a PermissionType bit, or an
accessRestrictions: name that is not an AccessRestrictionType bit. Both sets are
OPC UA's own, so the names take no namespace prefix:
permissions: [Browse, ns:Something] # ✗ a prefix points at nothing
permissions: [all, Read] # ✗ all stands alone
permissions: [Browse, Read, Call] # ✓
permissions: [all] # ✓ every permission valid for the node's NodeClass
accessRestrictions: [SigningRequired, EncryptionRequired]
DSL-E-PERM-003 — permission set not usable
A permissionSet: names no entry of permissionSets:, or the node also writes
rolePermissions: or accessRestrictions: itself. A node takes its permissions from one
place:
permissionSets:
adminOnly:
rolePermissions:
- role: ua:SecurityAdmin
permissions: [all]
accessRestrictions: [SigningRequired, EncryptionRequired]
...
- browseName: Secret
permissionSet: adminOnly # ✓
- browseName: Key
permissionSet: adminOnly # ✗ a set and its own keys
accessRestrictions: [SigningRequired]
DSL-W-PERM-004 — permission set not used
No node names this permissionSets: entry, so it grants nothing. Check the nodes meant
to use it for a misspelt name: those are reported as DSL-E-PERM-003.
Model file form
These describe the shape of the file, not the model in it. A model can be perfectly valid and still draw one.
DSL-W-FORM-KIND-IN-HEAD — kind: in the model document
kind: opens a tail document of a self-contained stream; document 1 is the
model and is marked profile: self-contained instead. A stray kind: in the
head flips generate onto the stream path with no table to read.
Put a --- separator before the line so it opens a tail document, delete it, or
let opcua-modeler pack write the tail.
DSL-W-FORM-NOT-SEALED — .opcua.yaml with no sealed table
The file carries the self-contained extension but holds no kind: symbols
document, so NodeIds are still read from and written to the .csv sidecar
rather than the file itself.
Run opcua-modeler pack to seal the table in, or rename it back to
*.model.yaml to keep the pair form.
DSL-I-FORM-MISNAMED — sealed stream not named .opcua.yaml
The file is a sealed self-contained stream but is not named *.opcua.yaml, so
editors bind the single-document model schema to it and flag every line of a
perfectly correct tail.
DSL-W-FORM-ORPHAN-CSV — sidecar beside a sealed stream
A .csv symbol file sits next to a sealed stream. The embedded table is the
only ledger that is read; the CSV is ignored and will drift out of date.
Doctor — file and ledger health
opcua-modeler doctor reports these. They are about NodeId stability across
regenerations, which is what keeps a published NodeSet's ids meaningful.
DSL-E-DOCTOR-MISSING — file does not exist
A file named on the command line is not there.
DSL-E-DOCTOR-STREAM-PARSE — stream does not parse
The file looks like a self-contained stream but does not parse. Check the ---
separators and the kind: key of each tail document.
DSL-W-DOCTOR-NO-OWN-TABLE — no table for its own namespace
The file is a stream, but none of its kind: symbols documents is for its own
namespaceUri — so every NodeId is allocated afresh on the next generate.
DSL-W-DOCTOR-LEDGER-STALE — table sealed against an older model
Nodes added since have no id yet; nodes removed since are still listed. Not
fatal — generate re-seals — but worth knowing before a release rather than
after.
DSL-E-DOCTOR-DUPLICATE-ID — one id, two nodes
The same NodeId is assigned to two different browse names. Give one of them a fresh id by hand, regenerate, and compare the NodeSet2.xml.
DSL-E-DOCTOR-RECYCLED-ID — a retired id came back
An id is both retired and live. Retirement exists precisely to stop this: a
client that cached the old node now resolves it to a different one. Move the
live node to a fresh id above nextId.
DSL-E-DOCTOR-NEXTID — nextId is already in use
nextId is at or below an id that is already assigned or retired, so the next
node added would collide. Raise it above the highest id in use.
DSL-I-DOCTOR-NO-LEDGER — no symbol file
A pair-form model with no .csv. Every NodeId is allocated from scratch on the
next generate — harmless the first time, a renumbering of a published NodeSet
every time after. Generate once and keep the ledger under version control, or
pack to the self-contained form.
DSL-W-DOCTOR-OUTPUT-STALE — NodeSet older than the model
The generated .NodeSet2.xml is older than the model it came from, so it does
not describe the current model.
Dependency versions
These two report on the companion specifications you import, and are not conformance rules — nothing in your model is wrong.
DSL-W-DEP-VERSION — major version differs
A nodeset was built against a different major version of a dependency than the one being loaded. Worth reading: a major bump can move or remove types.
DSL-I-DEP-VERSION — newer, same major
A dependency is newer than the one the nodeset was built against, within the same major version. Informational, and the normal state of affairs.
OPC UA FX
These rules come from the OPC UA FX extension (@sterfive/opcua-modeler-ext-fx, ADR-010). They
check a model that imports fxData, fxAc or fxCm against OPC 10000-81 once it is compiled,
and point at the node that breaks the rule. An error is a "shall" of the specification; a warning
is a recommendation, or a requirement that holds only in some deployments.
DSL-E-FX-001 — FunctionalEntities holds only FunctionalEntities
OPC 10000-81 §6.2.2, Table 4 — the FunctionalEntities Folder holds only instances of a FunctionalEntityType subtype, or of a type implementing IFunctionalEntityType.
Move the node to the Assets folder if it is hardware, or give it a FunctionalEntity type.
DSL-E-FX-002 — Assets holds only Assets
OPC 10000-81 §6.2.2, Table 4 — the Assets Folder holds only instances of FxAssetType or a subtype, or of a type implementing the vendor and tag nameplates and IAssetRevisionType.
DSL-E-FX-003 — an Asset a FunctionalEntity uses is listed in Assets
OPC 10000-81 §6.2.2, Table 4 — Assets "shall include all assets that are referenced from the FunctionalEntities".
A FunctionalEntity names the Asset it runs on with IsHostedBy (or IsExecutingOn); organize that
Asset in the AutomationComponent's fxAc:Assets folder. A built-in part of a listed Asset
(HasBuiltInAsset) counts as listed.
DSL-E-FX-004 — what an Inputs or Outputs folder may hold
OPC 10000-81 §6.4.4, §6.4.5 — InputData holds only Variables, SubscriberCapabilities or nested
<InputGroup>; OutputData only Variables, PublisherCapabilities or nested<OutputGroup>.
Group related Variables in a nested folder of type fxAc:InputsFolderType or
fxAc:OutputsFolderType rather than an Object.
DSL-E-FX-005 — unique Variable names in an Inputs or Outputs folder
OPC 10000-81 §6.4.4, §6.4.5 — the BrowseNames of the Variables in the folder shall be unique.
Two Variables differing only by namespace count as the same name. A nested group separates them.
DSL-W-FX-006 — String and ByteString data need a maximum length
OPC 10000-81 §6.4.4, §6.4.5 — with PubSub periodic data in a fixed layout, a String Variable carries MaxStringLength, a ByteString Variable MaxByteStringLength.
A warning, since only a fixed-layout exchange requires it; declare the property to keep the model usable there.
DSL-W-FX-007 — an AutomationComponent goes under FxRoot
OPC 10000-81 §12.2 — FxRoot is the standard entry point for all instances related to OPC UA FX.
Use organizedBy: /ua:Objects/fxData:FxRoot.
DSL-W-FX-008 — one ConnectionManager per Server
OPC 10000-81 §12.3 — a Server supporting a ConnectionManager has only one instance.
fxCm already provides it, as FxRoot/ConnectionManager: do not declare another one.
DSL-E-FX-101 — an fx: block with a key it does not know
An fx: block holds exactly one of functionalEntity, automationComponent and asset, and
each takes its own keys (see the FX vocabulary). An
instance takes automationComponent only, the other two describe types; it may also state its
links, hostedBy and executingOn, each one path or a list of paths.
DSL-E-FX-102 — an fx: name that names nothing
A name in a ControlGroup's restrict, block or related is one of the FunctionalEntity's own
inputs, outputs, configuration variables or methods (or a path containing /). A hostedBy or
executingOn on a type names an asset of the same automationComponent block.
DSL-E-FX-103 — an author version that is not Major.Minor.Build.SubBuild
author: { version: 1.0.0.0 } becomes the FxVersion structure of AuthorAssignedVersion
(OPC 10000-81 §6.4.2): four whole numbers separated by dots.
Silencing a diagnostic
Per code, or by prefix:
opcua-modeler generate -i model.yaml --silence DSL-W-NAMING-005,DSL-W-UNIT-
or in the model itself, so the decision travels with it:
documentation:
options:
lint:
silence: [DSL-W-NAMING-005]
Prefer fixing to silencing. A silenced warning is a decision, so leave a comment saying why — the next reader cannot see what you knew.