Diagnostics
Every issue the linter can report, with its trigger, an example, and the remedy. Codes are stable identifiers: once allocated, a code's meaning is immutable. New conditions get new codes.
If you are running exd lint and want to know what a code means, this is the page. If you are debugging an upload that failed at the server, the server returns the same codes in its manifest_lint_failed response.
Severity
| Severity | Codes | Effect on upload |
|---|---|---|
| Error | E0xx | Schema violation. The manifest is invalid. Upload rejected with manifest_lint_failed. |
| Warning | W0xx | Likely problem. The manifest is valid but suspicious. Upload accepted. CI MAY treat warnings as blocking via --deny-warnings. |
| Info | I0xx | Informational hint. The manifest is fine. Upload accepted. |
LintReport.passed is true iff the error bucket is empty. Warnings and infos do not affect it.
Conformance levels
Every requirement in the manifest format applies at one of three levels:
| Level | Enforced by | Effect of violation |
|---|---|---|
| Schema | TOML parser + linter (E0xx codes) | Manifest is rejected. Server upload returns manifest_lint_failed (HTTP 422). |
| Lint | Linter only (W0xx and I0xx codes) | Manifest is accepted, but the linter emits a warning or info. CI MAY treat warnings as errors via --deny-warnings. |
| Convention | Reviewers, dashboards, documentation | No automated enforcement. Affects readability, ownership, and team workflow. |
Schema-level rules use MUST in the reference text. Lint-level rules use SHOULD for recommendations and MUST for the linter's behavior itself ("the linter MUST emit W004 when …"). Convention-level rules use prose without normative keywords.
The buckets are mutually exclusive: an error never appears in the warning or info bucket and vice versa. Diagnostic codes are stable identifiers — once allocated, a code's meaning is immutable. New conditions get new codes.
Numeric index
Errors
| Code | One-line summary |
|---|---|
E001 | TOML parse failure, or schema_version missing / invalid |
E004 | Undeclared variant on an env block or rule |
E005 | Missing segment reference |
E006 | Invalid bucket range or entity_id_attribute |
E009 | Rule missing required field |
E010 | Unknown environment (typed mode) |
E011 | Segment lacks predicate and bucket |
E012 | Circular segment reference |
E013 | Deprecated inline-targeting field |
E014 | flag.type invalid, or variant value type mismatch |
E015 | Predicate shape error |
E016 | Unknown field on a structural table |
E017 | Namespace slug mismatched with directory |
E018 | Symlink in manifest tree |
E019 | File size exceeds 256 KB |
E020 | Empty or missing [flag.variants] |
E021 | Invalid variant key |
E022 | Invalid flag.lifecycle value |
E023 | [namespace.environments] declared but empty |
E024 | Invalid environment slug |
E025 | [segment] table missing |
E026 | Non-string segment or variant on a rule |
E029 | Non-finite float in variant value |
E030 | Invalid namespace slug |
E031 | Invalid flag filename |
E032 | Invalid segment filename |
E033 | Empty values = [] on in / not_in |
E034 | Attribute type conflict across predicates |
E036 | Rule declares both segment and predicate |
E037 | [flag.environments._] block missing |
E038 | [flag.environments._] missing variant |
E039 | testing = true without rules, or on _ |
Warnings
| Code | One-line summary |
|---|---|
W002 | Retired flag still has rules |
W003 | Flag has no rules anywhere |
W004 | Bucket segment without explicit salt |
W005 | Predicate nesting exceeds 5 levels |
W007 | Empty compound predicate array |
W008 | Minor schema_version mismatch across files |
W009 | Subdirectory under flags/ or segments/ |
W010 | namespace.display_name empty when declared |
W011 | flags/ or segments/ directory missing |
W012 | Duplicate segment in rules within the same environment |
W013 | Segment defined but never referenced |
W014 | Variant defined but never used |
W015 | Substring operator with empty-string operand |
W016 | Empty per-env block |
Infos
| Code | One-line summary |
|---|---|
I001 | Flag has no owner |
I002 | Flag has no description |
I003 | Segment has no description |
Reserved (no current emission)
| Code | Reason |
|---|---|
W001 | Unreachable rule via subsumption — reachability analysis not implemented. Today, the simpler "duplicate segment in same env" case is handled by W012. |
E002, E003 | Retired in schema 0.1. Were "missing or mismatched flag.key / segment.key". Both fields are gone — the key is the filename stem. Declaring key = "..." now raises E016. |
E007, E008 | Reserved. Were "duplicate flag/segment key". Structurally unreachable — a filesystem cannot return two regular files with the same name in the same directory. |
E027, E028, E035, W006 | Retired in schema 0.1, replaced by the per-env-complete resolution model. See resolution. |
I004 | Reserved for a future environment-write-gating diagnostic. |
E040+ / W017+ / I005+ | Future minor-version diagnostics. |
The numbering is sparse on purpose so future minor versions can introduce diagnostics without renumbering existing ones.
Errors by author intent
When editing namespace.toml
E001, E016, E017, E023, E024, E030, W010
When editing flags/<key>.toml
E001, E004, E005, E009, E010, E013, E014, E016, E019, E020, E021, E022, E026, E029, E031, E036, E037, E038, E039, W002, W003, W012, W014, W016
When editing segments/<key>.toml
E001, E005, E006, E011, E012, E015, E016, E019, E025, E032, E033, W004, W005, W007, W013, W015
Manifest-wide (cross-file)
E018 (symlinks), E034 (attribute type conflict), W008 (minor version mismatch), W009 (subdirectory), W011 (missing directories)
Error catalog (E0xx)
E001 — TOML parse failure, or schema_version malformed
Triggers when a file is empty, contains invalid TOML, or its schema_version field is absent, not a string, or does not match <u64>.<u64> shape. Examples that fail: "1", "1.0.0", "abc", "v1.0", "1.x", "x.0", "".
Only shape is checked — "99.0" passes lint but the server later rejects it with schema_version_mismatch.
Remedy. Add or correct schema_version = "0.1" at the top of the file; fix any TOML syntax error in the message.
E004 — Undeclared variant
Triggers when a [flag.environments.<env>].variant or a rule's variant references a key not declared in [flag.variants] (any env, including _).
Variants are per-flag — a variant declared in another flag does NOT satisfy this one.
Remedy. Add the variant to [flag.variants], or correct the typo.
E005 — Missing segment reference
Triggers when a flag rule's segment field, or a { segment = "..." } reference in a predicate (top-level or nested in and / or / not), names a segment with no corresponding segments/<key>.toml. A rule's segment = "" (empty string) also fails the lookup and raises E005.
Remedy. Create the missing segment file, fix the typo, or remove the reference.
E006 — Invalid bucket range
Triggers when a [segment.bucket] table has any of: start missing, end missing, entity_id_attribute missing or empty, start < 0, end > 9999, or start > end.
Boundary values that do NOT trigger: start = 0, end = 0; start = 0, end = 9999; start = 9999, end = 9999; start = end anywhere in range.
Remedy. Set start and end such that 0 ≤ start ≤ end ≤ 9999; set a non-empty entity_id_attribute. See buckets.
E009 — Rule missing required field
Triggers when a rule table omits variant, or declares neither segment nor predicate. Two malformed rules in the same array produce two E009 diagnostics.
A rule with segment = "" does NOT trigger E009 — the field is present but empty (lookup fails as E005). A rule with both segment and predicate triggers E036, not E009.
Remedy. Add the missing field. See flag § Rule fields.
E010 — Unknown environment (typed mode)
Triggers when typed-env mode is active ([namespace.environments] declared) AND a flag declares [flag.environments.<env>] for a slug not present in [namespace.environments]. Matching is case-sensitive.
The reserved name _ is always accepted and never reports E010. In untyped-env mode, E010 does not fire (any pattern-valid env slug is accepted).
Remedy. Add the env to namespace.toml or correct the slug in the flag.
E011 — Segment lacks predicate and bucket
Triggers when a [segment] table is present but neither [segment.predicate] nor [segment.bucket] is declared.
Remedy. Add a [segment.predicate] (for an audience) or [segment.bucket] (for a percentage rollout), or both.
E012 — Circular segment reference
Triggers when segment predicates form a cycle: self-loops (a → a), two-cycles (a → b → a), longer cycles, cycles through nested compounds, or multiple disjoint cycles. A cycle that goes through a missing segment produces E005 only — the broken edge is not a cycle.
Remedy. Break the cycle by extracting a shared sub-predicate into a leaf segment, or by replacing one of the segment references with an inline attribute predicate.
E013 — Deprecated inline-targeting field
Triggers when a rule contains any of the legacy fields condition, rollout, or percentage. These predate the segment-based targeting model.
Multiple deprecated fields in a single rule produce one E013 listing all offending field names.
Remedy. Rewrite the rule to reference a segment. Express predicates as [segment.predicate] and percentage rollouts as [segment.bucket].
E014 — flag.type invalid, or variant value type mismatch
Triggers when flag.type is missing, set to an unrecognized value, when a variant value's TOML type does not match the declared flag.type, or when a variant uses the reserved table-form ([flag.variants.<key>] with nested value / description).
Remedy. Set flag.type to one of the five permitted values; correct the variant value's TOML type. See flag § Per-type variant rules.
E015 — Predicate shape error
Triggers when a predicate atom's operator/operand shape is malformed, or a compound's value has the wrong TOML shape. The full trigger list is in predicates § Common diagnostics.
Remedy. Use the operator's documented operand shape. See predicates § Operator quick reference.
E016 — Unknown field on a structural table
Triggers when a closed-field table contains a field outside its recognized set. The closed-field tables in schema 0.1:
| Table | Recognized fields |
|---|---|
[namespace] | slug, display_name, description, telemetry_enabled, raw_entity_ids, private_attributes |
[flag] | type, description, owner, lifecycle, tags, private_attributes, variants, environments |
[flag.environments.<env>] | variant, rules, testing |
[[flag.environments.<env>.rules]] entry | segment, predicate, variant, description (legacy condition / rollout / percentage → E013) |
[segment] | description, predicate, bucket |
[segment.bucket] | entity_id_attribute, salt, start, end |
| Predicate atom table | attribute, op, value, values |
| Predicate compound table | exactly one of and, or, not |
| Predicate segment-reference table | segment |
Env values under [namespace.environments] are the only forward-compatible site and silently accept unknown fields.
Common occurrences:
- Retired field names.
value,enabled,key, top-level[[flag.rules]]from the pre-0.1 layered model. default_varianttypo. On[flag.environments.<env>],E016carries a hint pointing atvariant. (This is the one rename hintE016carries; other unknown-field cases leave the remedy to the author.)- Rule typos.
segments/varient, env-block keys lifted onto a rule (enabled,value), embedded predicate fragments (attribute,op,and,or,not) all produceE016.
Remedy. Remove the unknown field, or correct the typo.
E017 — Namespace slug mismatched with directory
Triggers when namespace.toml is present, [namespace] is present, namespace.slug is declared, AND the declared slug does not equal the directory name. A missing namespace.toml or missing slug field falls back to the directory-name slug; E017 fires only when a slug has been declared and it disagrees with the on-disk shape (almost always a stale rename).
Remedy. Set namespace.slug to the directory name, rename the directory, or remove the slug field.
E018 — Symlink in manifest tree
Triggers when any path inside the flag-namespace directory tree is a symbolic link rather than a regular file or directory. Symlinks compromise reproducibility because the same tree may resolve differently on different machines.
Remedy. Replace the symlink with a regular file (or, if the target is in the same flag namespace, copy the contents).
E019 — File size exceeds 256 KB
Triggers when a .toml file inside the manifest is larger than 256 KB. The cap exists to prevent runaway JSON variant payloads.
Remedy. Slim down the file. If a single flag genuinely needs more than 256 KB of variant payload, split the configuration into multiple flags or store the bulk data outside exd.
E020 — Empty or missing [flag.variants]
Triggers when the flag file has no [flag.variants] table, or the table is present but empty.
Remedy. Declare at least one variant. A flag with zero variants cannot evaluate.
E021 — Invalid variant key
Triggers when a key inside [flag.variants] does not match [a-z][a-z0-9_-]* (max 63 chars).
Remedy. Rename the variant to satisfy the pattern.
E022 — Invalid flag.lifecycle value
Triggers when flag.lifecycle is set to a string other than "development", "active", or "retired".
Remedy. Use one of the three permitted values, or omit the field to default to "active".
E023 — [namespace.environments] declared but empty
Triggers when namespace.toml is present AND declares [namespace.environments] with zero entries. A missing [namespace.environments] (or missing namespace.toml) is not E023 — it selects untyped-env mode.
Remedy. Either declare at least one environment, or delete the empty table to opt into untyped-env mode.
E024 — Invalid environment slug
Triggers when a key in [namespace.environments] does not match [a-z][a-z0-9-]* (max 63 chars; underscores forbidden).
Remedy. Rename the environment.
E025 — [segment] table missing
Triggers when a segment file parses cleanly but does not declare a [segment] table.
Remedy. Add [segment] with at least a description plus either predicate or bucket.
E026 — Non-string segment or variant on a rule
Triggers when a rule's segment or variant field is present but is not a TOML string (e.g., segment = 42, variant = true, an array, or a table).
Remedy. Quote the value as a TOML string.
E029 — Non-finite float in variant value
Triggers when a variant value contains nan, inf, or -inf. The check covers:
- A
flag.type = "float"variant value that is non-finite at the top level. - A
flag.type = "json"variant whose inline table or array contains a non-finite float at any nesting depth.
TOML 1.0 syntactically permits these literals, but JSON has no native representation for non-finite numbers; permitting them in variant values would force every SDK to invent a wire encoding.
Remedy. Use only finite float values. If a sentinel for "no limit" is needed, declare a documented large finite number (e.g., f64::MAX) or use an integer/string flag.
E030 — Invalid namespace slug
Triggers when namespace.slug is present but does not match [a-z][a-z0-9-]* (max 63 chars, no underscores, lowercase first character).
E017 (missing [namespace] / missing slug / slug-vs-directory mismatch) takes priority when the slug field is absent. E030 fires when a slug is present but malformed; if it also fails to match the directory, both E017 and E030 fire.
Remedy. Rename the slug to satisfy the pattern; rename the manifest directory to match.
E031 — Invalid flag filename
Triggers when a .toml file in flags/ has a stem that does not match [a-z][a-z0-9_-]* (max 63 chars). The stem is the flag key (no flag.key field).
The file is dropped before per-file lint, so an invalid filename produces exactly one E031 and no follow-on diagnostics from its TOML contents.
Remedy. Rename the file.
E032 — Invalid segment filename
Mirror of E031 for segment files in segments/.
Remedy. Rename the file.
E033 — Empty values = [] on in / not_in
Triggers when a predicate atom whose operator is in or not_in declares values = []. An empty in would always be false; an empty not_in would always be true. Both forms are degenerate.
Remedy. Either populate values with at least one scalar operand, or replace the atom with a tautology ({ attribute = "<always-set>", op = "is_set" }).
E034 — Attribute type conflict across predicates
Triggers when the same attribute name is used in two or more predicate atoms (across segments, inline flag rules, and entity_id_attribute on bucket segments) under operators / operand shapes that imply incompatible types. The linter walks every well-formed atom and infers a type per attribute:
| Operator | Inferred type for the attribute |
|---|---|
eq, neq | type of the scalar operand (bool / integer / float / string) |
lt, lte, gt, gte | number (matches integer and float) |
in, not_in | element type of values |
contains, not_contains, starts_with, ends_with | string |
semver_* | semver (string-shaped, narrower than string) |
is_set, is_not_set | (no constraint) |
[segment.bucket].entity_id_attribute | string |
The first site to fire fixes the inferred type; later disagreements emit E034 against the second site, with a message naming the first.
Compatible pairings do NOT fire: string ↔ semver, integer ↔ float under numeric operators.
Remedy. Pick a single canonical type for the attribute. Rename one site or rewrite an operand. Run exd schema to see the inferred type per attribute and the source sites.
E036 — Rule declares both segment and predicate
Triggers when a flag rule declares both segment = "..." and predicate = { ... }. The two are mutually exclusive — a rule MUST identify its audience exactly one way.
Remedy. Pick one. Use segment = "..." when the audience is named and reusable; use inline predicate = { ... } for one-off targeting.
E037 — [flag.environments._] block missing
Triggers when a flag file declares neither [flag.environments._] nor any block under [flag.environments]. The _ catch-all is mandatory — without it the flag has no fallback for environments that don't declare their own block.
A flag that declares named env blocks but no _ block also raises E037. Named envs cannot serve as the fallback.
Remedy. Add [flag.environments._] with at least a variant field. See resolution § The catch-all _.
E038 — [flag.environments._] missing variant
Triggers when a flag declares [flag.environments._] but the block does not declare variant. The catch-all MUST declare a fallback variant so resolution always terminates.
E004 (undeclared variant) takes priority when variant IS declared but references a key not in [flag.variants].
Remedy. Add variant = "<variant-key>" to the _ block.
E039 — testing = true misused
Triggers when either:
- A
[flag.environments.<env>]block declarestesting = truebut does not declarerules(or declaresrules = []). The gate has nothing to gate. - A
[flag.environments._]block declarestesting = true. The catch-all is the resolver-of-last-resort for non-opted-in callers; gating it has no audience.
E001 takes priority when testing is non-bool. E039 does NOT fire when testing = false is paired with no rules (a no-op, harmless).
Remedy. Either remove testing = true, or add a rules array. For the _-block case, move the testing-gated rules into a named env block. See resolution § The rollout workflow.
Warning catalog (W0xx)
W002 — Retired flag still has rules
Triggers when flag.lifecycle = "retired" and any environment has rules. One W002 fires per flag regardless of how many environments still carry rules.
Remedy. Either move the flag back to lifecycle = "active" or remove the rules and proceed with retirement (audit usage in code, then delete the file).
W003 — Flag has no rules anywhere
Triggers when a flag declares no rules in [flag.environments._] AND no rules in any named env block. This may be intentional (kill-switch pattern). The warning surfaces it for visibility.
Remedy. Either accept the warning (kill-switch pattern) or add at least one rule.
W004 — Bucket segment without explicit salt
Triggers when a [segment.bucket] table omits salt or sets salt = "". The bucket still works (falls back to the segment key) but renaming the segment will rebucket every entity.
Remedy. Set an explicit salt, typically a stable rollout or experiment name.
W005 — Predicate nesting exceeds 5 levels
Triggers when a [segment.predicate] is nested more than 5 levels deep, counting the chain of and / or / not keys. Atom tables and segment-reference tables do not count.
Remedy. Extract inner predicates into named segments and reference them via { segment = "..." }.
W007 — Empty compound predicate array
Triggers when a predicate contains and = [] or or = []. Vacuous truth is well-defined (true for and, false for or) but the empty list is more often a mistake.
Remedy. Populate the array, or replace the compound with an explicit tautology / negation.
W008 — Minor schema_version mismatch across files
Triggers when two or more files inside the same flag namespace declare different minor versions within the same major (e.g., "1.0" and "1.2"). The upload is still accepted.
Remedy. Run exd manifest migrate --to <minor> to advance every file to the same minor.
W009 — Subdirectory under flags/ or segments/
Triggers when a subdirectory exists under flags/ or segments/. The linter does NOT descend; the warning surfaces the unexpected layout.
Remedy. Move the subdirectory's contents into the parent directory or out of the manifest tree entirely.
W010 — namespace.display_name empty when declared
Triggers when namespace.display_name is present and equal to "". The field is optional; omitting it defaults to the slug. Declaring it as empty is almost always an oversight.
Remedy. Set display_name to a human-readable string, or remove the field.
W011 — flags/ or segments/ directory missing
Triggers when the flag-namespace root does not contain a flags/ or segments/ directory. The linter accepts their absence during initialization; the warning surfaces the missing directory.
Remedy. Create the missing directory (it MAY be empty).
W012 — Duplicate segment in rules within the same environment
Triggers when two or more rules inside the same [flag.environments.<env>] block declare the same segment. Because the loop returns on the first match, every rule after the first against that segment is unreachable.
One W012 fires per shadowed rule. A rule in _ and a rule in a named env block are NOT in conflict — env rules completely replace _'s rules for that env.
Remedy. Remove the shadowed rule, or change one rule's segment.
W013 — Segment defined but never referenced
Triggers when a segments/<key>.toml file declares a segment whose key is not referenced by any flag rule or any other segment's predicate. The segment is dead data.
A self-reference does NOT count as "used" (and typically also fires E012).
Remedy. Reference the segment from at least one flag rule (or from another segment's predicate), or delete the file. Use --allow W013 during transitional periods.
W014 — Variant defined but never used
Triggers when a [flag.variants] entry declares a variant whose key is not referenced by any [flag.environments.<env>].variant (including _) and not by any rule's variant field across the entire flag. The variant is unreachable.
Remedy. Either add a rule that returns the variant, or remove the variant from [flag.variants].
W015 — Substring operator with empty-string operand
Triggers when a predicate atom uses contains, not_contains, starts_with, or ends_with with value = "". Mathematically degenerate (every string contains, starts with, and ends with the empty string).
Remedy. Replace value = "" with the substring/prefix/suffix the author actually meant. For an intentional always-true atom, use op = "is_set".
W016 — Empty per-env block
Triggers when a named [flag.environments.<env>] block (<env> ≠ _) declares neither variant nor rules. Every step of resolution falls through to _ for this env — the block is structurally redundant.
W016 does NOT fire on [flag.environments._] — an empty _ block already triggers E038, the more severe diagnostic.
Remedy. Add at least one of variant or rules, or delete the block.
Info catalog (I0xx)
I001 — Flag has no owner
flag.owner is absent or empty. Set it to a team handle.
I002 — Flag has no description
flag.description is absent or empty. Write a short prose description.
I003 — Segment has no description
segment.description is absent or empty.
Structural notes (no separate code)
- Empty manifest directory (no
namespace.toml, noflags/, nosegments/): lint succeeds. Slug = directory name; untyped-env mode; empty flag and segment maps. - Missing
flags/: lint succeeds, no flag diagnostics, segments still validated. - Missing
segments/: lint succeeds, no segment diagnostics; flag rules referencing any segment all emitE005. - Missing
namespace.toml: lint succeeds; untyped-env mode with all defaults applied. - Non-
.tomlfiles inflags/andsegments/: silently ignored. - Subdirectories under
flags//segments/: silently skipped (the linter only reads regular files). - Invalid filenames are dropped before per-file lint: a
.tomlwhose stem fails the key pattern produces exactly oneE031/E032; the file's contents are not parsed. - All diagnostics are collected: emitting
E020does NOT suppressE004/E009/E010in the same file. - Deterministic traversal:
flags/andsegments/are walked in lexicographic order so cross-file diagnostics fire deterministically. - Diagnostic file paths are relative to the manifest root.
CLI flags that affect output
| Flag | Effect |
|---|---|
--format json | Emit JSON instead of human-readable form. |
--deny-warnings | Exit non-zero if any warning is present (treat warnings as errors). |
--quiet | Suppress per-diagnostic lines; print only the summary. |
--allow <CODE> | Suppress a specific code from the exit status. Repeatable. Useful during incremental migrations. |
--schema-major <N> | Reject any file whose schema_version major is not <N>. |
These affect the CLI experience, not the wire format of the report. The diagnostic codes themselves are stable regardless of flags.
Output formats
Human-readable (default)
flags/express-checkout.toml:22 error E004 Variant 'maybe' is not declared in flag.variants
segments/checkout-redesign-rollout-10.toml:34 error E006 Bucket range must satisfy 0 <= start <= end <= 9999
2 errors, 0 warnings, 0 infos
JSON (--format json)
{
"namespace": "payments",
"manifest_version": null,
"errors": [
{
"code": "E006",
"severity": "error",
"file": "segments/checkout-redesign-rollout-10.toml",
"line": 34,
"message": "Bucket range must satisfy 0 <= start <= end <= 9999"
},
{
"code": "E004",
"severity": "error",
"file": "flags/express-checkout.toml",
"line": 22,
"message": "Variant 'maybe' is not declared in flag.variants"
}
],
"warnings": [],
"infos": [],
"passed": false
}
CI integrations should consume the JSON form. Severity is rendered as the lowercase strings "error", "warning", "info". Match on code only — message text is not stable across versions.
Report structure
A LintReport carries:
| Field | Type | Description |
|---|---|---|
namespace | string | The flag-namespace slug. Falls back to the directory name when namespace.toml does not declare a slug. |
manifest_version | integer / null | Server-side only; null for a local lint. |
errors, warnings, infos | arrays of diagnostics | One bucket per severity. |
passed | bool | true iff errors is empty. Warnings and infos do not affect this. |
Each diagnostic carries:
| Field | Type | Description |
|---|---|---|
code | string | The stable code, e.g. "E001". |
severity | string | "error" / "warning" / "info". |
file | string | Path relative to the manifest root (e.g., flags/checkout-redesign.toml). |
line | integer | 1-based line number. Today the linter often reports 1; future versions will track exact lines. |
message | string | Human-readable description. Not stable across versions — match on code. |
See also
exd lint— the CLI that produces these diagnostics.- The file-reference pages — each lists the diagnostics most likely to fire on it: namespace, flag, segment.
- The concept pages — predicates, buckets, resolution, evaluation-context — explain the semantics each diagnostic enforces.