Linting¶
The [lint] section controls which diagnostics ubCode reports.
Use it to suppress noisy warnings globally,
override suppression for specific codes in the LSP,
or target ignores to particular files or message patterns.
Minimal example¶
[lint]
ignore = ["block.title_line"]
[lint.per-file-ignores]
"tests/**/*.rst" = ["needs.dead_link"]
Core options¶
- ignore
Type:
array(default:[])List of linting error codes to ignore globally across the project.
- lsp_select
Type:
array(default:[])List of linting codes to specifically enable in Language Server Protocol (LSP) file diagnostics. This setting overrides the ignore list, allowing you to see specific errors in your editor even if they’re globally ignored.
[lint]
# List of linting codes to ignore
ignore = ["block.title_line"]
# A list of linting codes to select in LSP file diagnostics
# This overrides the ignore list.
lsp_select = ["block.title_line"]
Code matching and .* wildcards¶
Everywhere a list of diagnostic codes is configured —
ignore, lsp_select, the code lists of per-file-ignores,
and the codes scope of message-ignores —
an entry matches a diagnostic in one of two ways:
Exactly:
"needs.dead_link"matches only theneeds.dead_linkcode.As a family wildcard: a trailing
.*matches a whole dot-namespaced family —"toctree.*"matches everytoctree.<subcode>diagnostic, and also the bare family code itself (so"config.*"covers both the fine-grainedconfig.<subcode>diagnostics and the plainconfigones).
[lint]
# Suppress the whole std family — the dangling references
# (std.ref, std.doc, std.term) and the project-wide duplicates
# (std.duplicate_target, std.duplicate_label, std.duplicate_term)
# — plus one exact code.
ignore = ["std.*", "block.title_line"]
No other glob positions are supported:
entries like "*.ref", "con*", or a bare "*"
are treated as plain literals and match no real code.
A bare family name is not an umbrella:
ignore = ["config"] matches only a diagnostic whose code is exactly
config — it does not reach config.unknown_extension and its
siblings. To suppress a whole family, use the .* wildcard.
Configuration diagnostics (config and config.*)¶
Problems found while resolving ubproject.toml itself are reported
against the configuration file. The checks with a fine-grained code are
individually suppressible:
config.unknown_extension— a[parse].extensionsentry that looks like a typo of a known port name.config.unknown_extension_option— a key other thanactiveinside a[parse.extensions]entry table. The entry still switches its port; the key itself is ignored.config.extension_always_on— a[parse].extensionsentry switching off something built into ubCode (sphinx_needs), which stays active.config.extension_unsupported— a[parse].extensionsentry switching on an extension ubCode does not support (thesphinx.ext.autodocfamily,sphinx.ext.graphviz); it runs only undersphinx-build.config.invalid_extlink_template— a[parse.extlinks]entry with an invalid%stemplate.config.extlink_shadows_builtin— a[parse.extlinks]role name that would shadow a built-in role.config.extlinks_data_inert— a populated[parse.extlinks]table whose port is switched off in[parse].extensions, so none of its roles is registered. Most often an inherited= falsemeeting a child’s own table.config.unknown_default_role— a[parse].default_rolenaming an unknown role.config.conflicting_content_model— a directive registration whose body mode conflicts with a same-named built-in.config.conflicting_directive_registration— two config entries that register the same directive name at runtime.config.string_link_incomplete— a [needs.string_links] rule missing one of its four required keys.config.string_link_regex_invalid— a string-linkregexthat does not compile (including one using look-ahead, look-behind or a backreference, which this engine does not support).config.string_link_template_invalid— a string-linklink_urlorlink_namethat is not a valid template.config.string_link_unknown_field— a string-linkoptionsentry naming a field the project never declared.config.field_shadowed_by_identity— a project declares a field or link namedcontent, on any of [needs.fields], [needs.links],extra_optionsorextra_links.contentis the need’s own body, which no declaration can shadow. The declaration is kept, so nothing that renders today stops rendering — the option can still be set on a directive, and a link’s targets are still validated — but filters, tables, variant conditions, report templates andneeds.jsonall answer the body for that name, so the declared value is invisible to every one of them. Rename the field or link;ignoresilences the warning while you migrate. (idandtype, the other two un-shadowable names, are refused outright and report under the plainconfigcode.)config.schema_unknown_key— a key in a schemas.json rule that neither ubCode nor sphinx-needs accepts, such asselctforselect,propertesforproperties, or a JSON-Schema keyword the rule grammar has no place for. Such a key used to be ignored, which silently changed what the rule meant: a misspelledselectleft the rule with no filter, so it applied to every need, and a misspelled key insidevalidate.localproduced a rule that validated nothing at all. The message names the offending key, the rule and the keys accepted at that position. No rule from the file is applied while any such key remains, which is what sphinx-needs does too — it refuses to build at all.config.schema_missing_validate— a schemas.json rule with novalidatemember.validateis what says what to check, so such a rule enforces nothing at all, which used to happen silently. sphinx-needs requires the member outright. A rule whosevalidateis present but empty is not reported — it asks for nothing and gets nothing, which is a rule doing what it says. No rule from the file is applied while the member is absent.config.schema_invalid_value— a key in a schemas.json rule that both engines accept, whose value sphinx-needs constrains and ubCode found wrong: atypethat is not"object"at aselect, avalidate.localor anallOfelement, or not"array"on a network link block; arequiredthat is not an array of strings; anunevaluatedPropertiesthat is not a boolean; or a network link block that cannot be read at all (not an object, acontainsoritemsthat is not an object, aminContainsormaxContainsthat is not an integer — any integer is accepted, whatever its sign or size, because that is all sphinx-needs requires, and a negative bound is applied when the rule runs rather than refused when it loads). The message names the key, the rule, the value found and the value expected. All fourtypepositions used to be accepted silently. In aselector avalidate.localubCode ignores that value, so the check is for parity and clarity; inside anallOfelement it is compiled verbatim, which is the costly case —"type": "string"makes the element match no need, so the rule enforces nothing.requiredandunevaluatedPropertiesused to be warnings whose constraint was then dropped, so the rule ran without it, and an unreadable network link block was dropped whole in silence. No rule from the file is applied while any such value remains; measured at sphinx-needs 8.4.0,sphinx-buildaborts on each of the values listed here, and this code fires only where it does. Fix the value rather than ignoring the code:ignoresilences the report but the file stays refused, so no rule from it is applied andubc checkthen exits 0 on a project whose schema validation is switched off.config.schema_sphinx_needs_incompatible— a schemas.json construct ubCode honours but sphinx-needs rejects, sosphinx-buildfails on a file ubCode is happy with. In practice this is an extra keyword inside anallOfelement, such as anot. The rule keeps working; onlyignoreit if the project never builds with sphinx-needs.config.mount_invalid— a [[source.mounts]] entry whosemount_at,attach_toorentry_docis not a relative document name, or whosefileslist is empty. The mount is dropped.config.mount_unknown_key— a key on a mount entry that ubCode does not model. The key is ignored and the rest of the mount is honoured, so oneubproject.tomlcan be shared with sphinx-mounts.config.mount_at_root— a mount with nomount_at, so it is mounted at the document root where any file it contributes can take the name of a host document.config.mount_dead_option— a mount key its own mode never reads:includeorexcludeon afilesmount (which has no walk to filter), orattach_eachon adirmount, withoutattach_to, or beside a non-defaultentry_doc.config.mount_missing— a declared mount root that is not on disk. The mount contributes nothing this run and the pages it contributed on an earlier run are kept rather than reported as deleted.config.mount_attach— a mount whoseattach_torequest could not be honoured: the host document does not exist,toctree_indexis past the end of it, or the mount produced no document to attach. Not reported for a mount this variant gates off, which has nothing to attach by design.config.mount_gated— a mount whoseifgates it off for this variant, so it contributes no documents. Graded info, not warning: gating is what you asked for, and grading it a warning would failubc checkon every build of every variant that gates anything. It is reported at all — and reported even when nothing in the project references the bundle — because a gated mount is otherwise a silent absence of a whole tree that may live in another repository.config.mount_gated_contested— a gated mount that is not credited with the documents it removed, because at least one of them carries a name the build already uses. Toctree entries naming its pages then reporttoctree.nonexisting_documentrather than the gate. Also graded info: it explains a warning that fires elsewhere rather than being one.config.mount_invalid_condition— a mount whoseifis not a valid condition. The mount is gated off, in every variant, until the condition is rewritten.config.mount_condition_unevaluable— a mount whoseifcould not be evaluated against the variant data, an unknownvar.*key being the common cause. The mount is gated off.config.mount_excludes_root— a mount this variant gates off is the only root supplying[project] root_doc. This one refuses the whole configuration rather than reporting, soignoredoes not reach it: nothing resolves. The same posture asconfig.variant_source_excludes_rootbelow, and for the same reason.config.variant_sources_sphinx_unsupported— a project declares a variant-gating key: [[source.variant_sources]] rules, orifon a [[source.mounts]] entry.sphinx-buildreads either one only through sphinx-mounts at a release that supports it: without that, the two tools see different document sets. Graded info, not warning: it fires on every project that declares either key — ubCode cannot see what is installed on the Sphinx side, so it cannot tell you which case you are in — and grading it a warning would failubc checkon a correctly configured project.ignoresilences it once you have read it.config.variant_source_unknown_key— a key on avariant_sourcesrule that ubCode does not model. Ignored, and the rest of the rule honoured, for the same shared-ubproject.tomlreason asconfig.mount_unknown_key.config.variant_source_invalid— avariant_sourcesrule with an emptyfileslist. The rule is dropped, which is safe: it selected nothing.config.variant_source_invalid_condition— a rule whoseifis not a valid rule condition, or cannot be evaluated against the current variant data (an unknownvar.*key is the usual cause). The rule’s files are excluded — warn-and-exclude, the same contract theifdirective has. Silencing this code does not put the files back; it only hides the reason they are gone.
Two variant_sources problems are hard configuration errors rather than
lint findings, so ignore does not reach them — nothing resolves, so nothing
is linted:
config.variant_source_invalid_glob— a rule glob using{a,b}alternation or climbing out of the project with... Refused rather than skipped: skipping the rule would leave every file it names in the build, including the files its other patterns name.config.variant_source_excludes_root— a rule that is false for the current variant and would remove[project] root_doc. The message names the pattern to narrow.
All other configuration warnings
(for example an unknown needs.global_options key)
report under the plain config code.
[lint]
# Suppress just the typo check…
ignore = ["config.unknown_extension"]
# …or the whole configuration channel:
# ignore = ["config.*"]
Attention
Previously every configuration diagnostic reported under the single
config code, so ignore = ["config"] suppressed the whole channel.
The fine-grained codes are now the real lint codes, and a bare
"config" entry matches only the code-less configuration warnings —
replace it with "config.*" to keep suppressing everything.
Needs-domain diagnostics (needs.*)¶
Most needs.* codes are documented beside the directive or configuration key
they concern. One is worth naming here, because it is the only one raised by a
whole-PROJECT check rather than by reading a single file:
needs.cypher_vocabulary— a view directive’s:cypher:(Cypher query) references a label, relationship type or property key that does not exist anywhere in the project’s needs graph. openCypher runs such a query silently — the missing name reads asnull, so the view usually matches nothing or renders blank cells, though a null-tolerant test such asIS NULLcan instead make it match everything — and this is what says so, anchored on the:cypher:option, with the same did-you-mean notesubc query cypherprints.Like every whole-project code (
std.duplicate_docname, thetoctree.*family), it is reported byubc check, counted by theubc build htmlquality gate, and listed — with its position — in the editor extension’s diagnostics view. It is not an inline squiggle: the editor’s per-file underlines carry the parse and markup phases only, which is why theneeds.cypher_invalidon the very same option does underline and this one does not.One warning per directive, carrying every note its query produced, because a
:cypher:has a single source range for the whole query:warning[needs.cypher_vocabulary] --> index.rst:9:5 the needtable :cypher: query references vocabulary this project does not have: unknown label `ned` — did you mean `req`?; unknown property `staus` — did you mean `status`? (the query still runs — the missing name reads as null, so the result is not what the query says: usually no rows or blank cells, sometimes a full but wrong table)
It is recomputed for the whole project on every index pass, so it disappears by itself once the missing vocabulary exists — you do not have to re-save the file it was raised on. A directive written in an
.. include::``d fragment is reported against the FRAGMENT, with the including page named alongside it, so a ``per-file-ignoresglob on either path suppresses it. A known field that merely happens to be unset on some needs never raises it: the check tests the project’s schema, never any need’s data.Narrow it with
contains = "unknown label", scope it to a path withper-file-ignores("index.rst" = ["needs.cypher_vocabulary"]), or silence the class withignore = ["needs.cypher_vocabulary"].message-ignoresmatches the message TEXT only, so a rule naming a position such ascontains = "index.rst:9:5"never fires — useper-file-ignoresfor that. It is distinct fromneeds.cypher_invalid, which reports a query that does not parse or has the wrong shape — a different fault with a different fix, so the two are separately suppressible.
per-file-ignores¶
Type: object (default: {})
A mapping of glob patterns to lists of diagnostic codes. When a diagnostic’s source file matches a pattern, and the diagnostic code is in the associated list, the diagnostic is suppressed.
Paths are specified in POSIX format (forward slashes)
and are relative to the configuration file directory,
ensuring cross-platform compatibility.
During configuration resolution,
patterns are absolutised relative to the directory of the config file
that defines them.
This means patterns from an extend-ed parent config
are correctly resolved relative to the parent’s location,
not the child’s.
Standard glob syntax is supported (*, **, ?, [...]).
Invalid glob patterns are reported as configuration diagnostics and skipped.
A diagnostic with multiple file-based source locations is suppressed if any of its file locations matches at least one rule for the code.
[lint.per-file-ignores]
# Ignore dead links and field validation errors in test fixtures
"tests/**/*.rst" = ["needs.dead_link", "needs.invalid_field_value"]
# Ignore schema violations in legacy documentation
"legacy/**" = ["needs.schema_definition_violation"]
# Ignore duplicate needs in a specific file
"docs/generated/index.rst" = ["needs.duplicate"]
message-ignores¶
Type: array of objects (default: [])
A list of rules for suppressing diagnostics whose message contains a given substring. Each rule is an object with:
codes(optional): a list of diagnostic codes this rule applies to. If omitted or empty, the rule applies to all diagnostic codes.contains: a case-insensitive substring to match against the diagnostic message. If omitted or empty, the rule matches all messages for the specified codes (or all diagnostics ifcodesis also omitted).
This is useful for suppressing specific classes of validation errors, for example diagnostics about a known deprecated field.
# Suppress all diagnostics mentioning "deprecated_field"
[[lint.message-ignores]]
contains = "deprecated_field"
# Suppress only field validation errors mentioning a specific pattern
[[lint.message-ignores]]
codes = ["needs.invalid_field_value"]
contains = "legacy_option"
Source-mount confinement (build.mount_path_escape)¶
build.mount_path_escape reports a document contributed by a
[[source.mounts]] tree that references a file
outside that tree — an include, an image, a download or a diagram
:file: that climbs out of the mount.
Despite the build. prefix it is an indexing diagnostic, anchored at the
referring document, so unlike the ubc build html warnings below
per-file-ignores does apply to it. That is the only way to hold two
mounts to different policies, because ignore is project-wide per code:
[lint.per-file-ignores]
# Off for one trusted generated tree, still on for every other mount.
"generated/**" = ["build.mount_path_escape"]
# …or off for the whole project.
# [lint]
# ignore = ["build.mount_path_escape"]
Its severity is fixed at warning level. To make it fail a build, escalate with
[build.html] deny — deny = "warning" turns this
(and every other warning) into a non-zero exit.
Files no root claims (std.file_outside_roots)¶
Added in version 0.33.0.
std.file_outside_roots reports a file that matches your source patterns but
that no root claims: it lies outside the project’s source root
([source] dir, or the deprecated
[project] srcdir)
and outside every [[source.mounts]] root.
The message names whichever of the two keys your project actually writes.
Discovery walks the declared roots and nothing else, so such a file is not
discovered at all —
it is not indexed, it produces no page, and no :doc: or toctree entry can
name it.
This warning is the only thing that will tell you it is there.
It can only arise when the source root is an explicit subdirectory (or a directory beside the configuration folder): left unset, the source root is the configuration file’s own directory, which claims every file below it. For that default layout ubCode does not even look, so the check costs nothing.
Three ways to act on it, and they are what the message names:
move the file under the source directory (or under a mount root), which makes it a document;
add it to [source] extend_exclude, which stops discovering it — the right answer for a
README.mdsitting beside the project;.. include::it from a document, which is the right answer for a fragment. A file some document already pulls in this way is exempt and never reported: a fragment has no document name on purpose.
Use extend_exclude, not exclude.
exclude is the base list, so setting it replaces the default hygiene
patterns (.git, node_modules, _build, dist, .venv and the
rest) — which would silence the file you named and start looking inside a
vendored tree instead, earning a fresh std.file_outside_roots pointing
inside it.
extend_exclude adds to the defaults rather than replacing them.
The patterns this check honours are matched against the configuration folder — the tree it scans — rather than against a source root. That holds under [source] dir too, where the same patterns anchor at each source root for discovery: this pass walks the configuration folder, and a pattern compiled against a root that is not the tree being walked would exclude nothing here. It is the one place the configuration folder still decides anything once discovery follows the roots, and it is what makes a pattern you wrote to keep a directory out of your project keep it out of this report too.
Like build.mount_path_escape above it is an indexing diagnostic anchored at
the file itself, so per-file-ignores applies —
which is how one tree of loose files is silenced while the rest of the project
stays covered:
[lint.per-file-ignores]
# Off for one directory of notes, still on everywhere else.
"notes/**" = ["std.file_outside_roots"]
# …or off for the whole project.
# [lint]
# ignore = ["std.file_outside_roots"]
Ignoring this code project-wide also skips the filesystem pass that feeds it.
This check is a second, names-only walk of the configuration folder — it reads no
file, but on a large repository it is not free — so a project that has silenced
it stops paying for it as well.
It is the one place a [lint] setting changes what ubCode reads from disk, and
it is deliberate: a monorepo that does not want the check should not be charged
for it on every build.
per-file-ignores does not skip the pass, because a project that silences
one directory still wants the report for the rest.
One class of file this check does not cover: a file under a mount root
inside the configuration folder that the mount’s own walk does not yield.
A mount claims its whole subtree, so such a file is “claimed” here even though
nothing discovers it.
Two things put a file in that state.
The first is the mount’s own exclude — that absence is what your own mount
configuration asked for, rather than something to warn you about.
The second is a source or parser include pattern written with a directory
prefix (vendor/*.rst): such a pattern is matched relative to the mount’s own
root inside a mount, so it can stop matching there even though you named the
file.
If a file under a mount root has gone missing and you did not exclude it, check
your include patterns for a directory prefix.
Its severity is fixed at warning level, and [build.html] deny escalates it like any other.
Variant-excluded toctree entries (toctree.variant_excluded)¶
Added in version 0.33.0.
toctree.variant_excluded reports a toctree entry naming a document that
[[source.variant_sources]] removed from
the current variant’s document set.
The message names both the document and the if string that removed it, so
the rule to narrow is the one you are told about.
It replaces two codes that would otherwise be misleading:
toctree.nonexisting_document for an explicit entry (the name is not a
mistake — the page exists in another variant), and toctree.empty_glob for a
:glob: entry whose only matches were removed (the pattern is not empty —
this variant emptied it).
It is graded info, not warning, and does not fail ubc check.
In a 150% model a shared index that lists every edition’s pages is the normal
shape, so this fires on configurations that are entirely correct — once per
entry, on every build of every variant.
As a warning it would have failed the default exit policy on such a project,
and the obvious response would have been to ignore the code, which switches
the reclassification off for the case it exists to catch: a rule glob that
matched more than its author intended.
Info keeps the message where you can read it and leaves the exit code alone.
Silencing it is therefore cosmetic rather than a way to unblock a build — it removes the message from the output, and nothing else:
[lint.per-file-ignores]
# Quieter for the one index that lists every edition's pages.
"reference/index.rst" = ["toctree.variant_excluded"]
# …or quiet for the whole project.
# [lint]
# ignore = ["toctree.variant_excluded"]
Consider leaving it on: it is the only remaining place a too-broad rule is
visible, because a removed file is gone from every other product — no page, no
document name, no needs, nothing in needs.json.
If you want it enforced, [build.html] deny with
deny = "info" escalates it like any other finding.
The diagnostic is anchored at the containing document, so per-file-ignores
globs on the document that holds the toctree — not on the excluded page,
which this variant does not have.
Ambiguous inventory matches (intersphinx.ambiguous)¶
intersphinx.ambiguous reports a cross-reference that matched more than
one loaded intersphinx project — or more than one
object type — after finding nothing in the project itself.
It fires on :ref:, :term:, :doc:, :any:, a sphinx-design link
typed any, and the unqualified :external: form; a target already
qualified with a project key (:ref:`zulu:shared`,
:external+zulu:ref:`shared`) names one inventory and cannot be ambiguous.
The message says which project won and which also matched:
multiple inventory matches for 'shared': took 'zulu' (std:label), also matched by 'alpha' (std:label)
It is graded info, not warning, and never fails a build: the reference
resolves, to exactly the page it always did, and a sphinx-build is silent
about the collision entirely.
Two overlapping inventories are also normal — every Sphinx-generated
objects.inv ships the same handful of built-in labels — so this fires on
configurations that are perfectly correct.
Read it as a note about your configuration rather than a fault in the page.
It is worth reading because of how the winner is chosen: the inventories are
merged in project-name order, and the alphabetically last project wins a
collision.
Adding an inventory whose key sorts after an existing one therefore moves every
colliding link, silently — and so does renaming a project key.
The order the projects appear in ubproject.toml has no effect.
To pin one target, qualify it with the project key:
:ref:`zulu:shared`
:external+zulu:ref:`shared`
To silence the notice instead:
[lint.per-file-ignores]
# Quiet for the one page that references the overlapping project.
"reference/api.rst" = ["intersphinx.ambiguous"]
# …or quiet for the whole project.
# [lint]
# ignore = ["intersphinx.ambiguous"]
If you want it enforced, [build.html] deny with
deny = "info" escalates it like any other finding.
The equivalent collision reached through a Markdown link ([](#target)
or [](inv:…)) reports intersphinx.ref at warning level instead, and
fails a default build — because myst-parser warns on it and this side of
the family follows its own upstream.
The two codes are silenced separately.
Link-check findings¶
Added in version 0.34.0.
The seven linkcheck.* codes that ubc build linkcheck reports —
linkcheck.broken, linkcheck.anchor_missing,
linkcheck.redirect_permanent, linkcheck.redirect_temporary,
linkcheck.blocked, linkcheck.server_error and linkcheck.timeout —
go through this same configuration.
ignore suppresses a whole class,
message-ignores narrows one to particular messages,
and per-file-ignores suppresses classes for particular source files:
[lint.per-file-ignores]
# Redirects are expected in the archive; dead links there are not.
"archive/**" = ["linkcheck.redirect_permanent"]
That last one is the equivalent of Sphinx’s linkcheck_exclude_documents,
with no extra knob to learn.
per-file-ignores is applied per occurrence:
a rule silences the places the URL is written under its glob and leaves the same
URL’s other occurrences standing,
so one archived page cannot hide a dead link in the rest of the project.
A finding disappears only when every one of its occurrences is silenced.
ignore and message-ignores ask about the code and the verdict’s message,
both of which belong to the URL rather than to a place,
so those two silence the whole finding.
A URL that exists only as a need field has no source file to match,
and is never silenced by a path rule.
Suppressed findings are counted separately —
the summary line ends with N suppressed by [lint],
and --output-format json marks each one "suppressed": true and keeps its
code, so a report consumer can still see what was silenced.
They are not counted under their status class,
because a run that passes should not also announce a broken link.
To suppress by URL rather than by file or code, use [linkcheck] ignore, which also stops the request being made at all.
Each class carries its own default severity, and [linkcheck] deny sets the bar those severities are compared against — see Link checking for the table.
Build warnings¶
Added in version 0.31.0.
The build.* warnings that ubc build html reports
(build.directive_unhandled, build.search_index_large, and the rest)
go through this same configuration:
ignore suppresses one by code,
and message-ignores narrows a code to particular messages —
for instance a single unhandled directive name.
per-file-ignores does not apply to them:
a build warning is a whole-build finding with no source file to match against.
Narrowing happens before gating:
a code silenced here never reaches
the quality gate
that decides the exit code of ubc build html,
so silencing a code is enough to keep a build green
without lowering the project’s bar.
Changed in version 0.31.1: A warning belonging to one page now names it,
as a docname: prefix on the message:
warning[build.video_glob_unsupported]
guide/intro: a video source cannot be a wildcard pattern ...
The rest of the message is unchanged,
so a message-ignores pattern written against the message text keeps matching,
and you can narrow one to a single page by including the prefix
(contains = "guide/intro: a video source").
This applies to the warnings raised while rendering a particular page.
The unhandled-markup radars (build.directive_unhandled,
build.role_unhandled) and the diagram-decline codes
(build.diagram_file_unresolved, build.diagram_unconvertible,
build.plantuml_render_failed)
are also raised during rendering
but are site-wide aggregates over every page,
so they carry no prefix and name their example positions inside the message instead;
nor do the whole-build warnings (asset reads, stale files, the manifest write),
which belong to no page.
Two codes are the exception on the page-scoped side:
build.need_view_failed and build.need_view_truncated
name their own position as docname:line: (with the line number),
so they are not given a second prefix —
a narrowing pattern for either must use that form
(contains = "guide/intro:42:"), not docname: plus a space.
Changed in version 0.31.2: build.need_view_truncated joins build.need_view_failed
as a code that names its own docname:line: position.
It is raised once per view directive whose :max_items: cap
(its own, or the project-wide needs.views_max_items default)
dropped items from the rendered result:
warning[build.need_view_truncated]
index:16: view directive needlist #0 was truncated: showing the first 2 of 3 needs ...
Narrow it to one page the same way as its sibling —
contains = "index:16:" — or silence the whole code
with ignore = ["build.need_view_truncated"].
Like every build warning it counts toward
the quality gate,
so on the default bar a truncated view fails ubc build html
until it is narrowed here or the cap is raised.
Added in version 0.31.2: build.need_style_invalid is raised once per need per page whose
:style: carried a token that is not a valid CSS identifier
(an ASCII letter or underscore, then ASCII letters, digits, underscores or
hyphens) — so a need carded on two pages is reported for each.
Such a token becomes no class on the card;
valid tokens on the same need still apply:
warning[build.need_style_invalid]
index: need REQ_1: ignored invalid :style: token(s) "9bad", "has space" ...
It is an ordinary page-scoped code —
the message names the NEED and ubCode prefixes the page,
so narrow it with contains = "index: need REQ_1"
or silence the class with ignore = ["build.need_style_invalid"].
Like every build warning it counts toward
the quality gate,
so on the default bar a mistyped style fails ubc build html
until it is fixed or narrowed here.
Added in version 0.31.2: build.need_layout_unknown is raised once per page and unknown name
whose needs asked for a card design this project does not have —
neither a built-in one nor one of its own
[needs.card_layouts] designs.
The affected needs are listed on the one line (the first five, then a count),
because a mistyped [needs.fields.layout] default applies to
every need in the project and would otherwise print hundreds of
identical lines:
warning[build.need_layout_unknown]
index: unknown :layout: "Focus" on 7 need(s) (REQ_1, REQ_2, REQ_3, REQ_4, REQ_5 and 2 more): rendered with the default layout "clean" (valid: clean, complete, focus, debug, clean_l, ...; aliases: test, focus_f)
The valid: list is built from your project: the built-in designs
first, then any design [needs.card_layouts] defines,
so a design you add appears in the message with no second edit.
The named default is your project’s
default_layout,
so the message says which design the card actually got.
The card renders with the default clean design;
a Sphinx-Needs build raises SphinxNeedLayoutException here,
which ends the build.
It is an ordinary page-scoped code —
the message names the NEEDS and ubCode prefixes the page,
so narrow it with contains = 'unknown :layout: "Focus"'
or silence the class with ignore = ["build.need_layout_unknown"].
Like every build warning it counts toward
the quality gate,
so on the default bar a mistyped layout fails ubc build html
until it is fixed or narrowed here.
Added in version 0.31.2: build.need_string_link_invalid is raised once per page and message
when a [needs.string_links] rule matched a
value but drew no link — its link_url or link_name failed to render,
or the target it rendered is not one this build will emit
(https://, http://, mailto: or a relative reference; anything
else, javascript: included, is refused rather than escaped).
warning[build.need_string_link_invalid]
index: the string link "tickets" drew no link for tickets on 7 need(s) (REQ_1, REQ_2, REQ_3, REQ_4, REQ_5 and 2 more) because its `link_name` failed to render (unknown filter: filter no_such_filter is unknown (in string_link:1)) — the value is shown as plain text
The value itself is kept, as plain text — a Sphinx-Needs build drops it
out of the page entirely in the template-failure case. Findings are
aggregated by message across the needs they apply to and across both
surfaces of a page (a card and a needtable hitting one broken rule report
once), because a bad template applies to every need carrying the field.
Narrow it with contains = 'the string link "tickets"'
or silence the class with ignore = ["build.need_string_link_invalid"].
Note
When using extend to inherit from a parent config,
per-file-ignores and message-ignores use replace semantics:
if the child config sets the field,
it completely replaces the parent’s value (rather than merging additively).
This is consistent with the behaviour of ignore and lsp_select.
To combine parent and child rules,
repeat the parent’s rules in the child config.
Deprecated since version 0.18.0: The rst_lint configuration section has been deprecated.
Use lint instead for all linting configuration.