Skip to main content

Finding Codes Reference

Every issue detected by Zenzic is tagged with a canonical finding code (Zxxx). This page is the quick-reference cheat sheet — severity, penalty, exit code, and the essential remediation path for every diagnostic signal.

Tier Model

Zenzic organises diagnostics into four operational tiers:

TierOwnershipFormatScope
CoreZenzicZxxxBuilt-in scanners and system findings
GovernanceZenzicZ6xxOpt-in policy checks ([governance])
PluginThird-party<plugin-id>:<code>External entry-point rules
CustomProject localZZxxx[[custom_rules]] declared in TOML

Stability Contract

The code registry is governed by immutable contract surfaces:

  • FROZEN_CODES: codes that cannot be renumbered or semantically changed without architecture-level approval.
  • NON_SUPPRESSIBLE_CODES: security codes that cannot be silenced inline.
  • PLUGIN_FORBIDDEN_EXITS: plugins are forbidden from emitting Exit 2/3 (reserved for core security semantics).
Deep-linking

Each code has a permanent anchor. You can link directly to a specific code using https://zenzic.dev/docs/reference/finding-codes#z101.

Category Overview

CategoryRangePurposeDefault SeveritySuppressible?
Z0xxMigration & CompatibilityEngine deprecation; migration guidanceerror❌ No (fatal abort)
Z1xxLink IntegrityBroken, empty, circular links; orphaned pages; path issueserror/warning/info✅ Yes
Z2xxSecurity (credential scanner)Secret detection; path traversal; security incidentswarning/security_breach/security_incident🔒 Never
Z3xxReference IntegrityDangling/duplicate reference definitionserror/warning✅ Yes
Z4xxStructureDirectory indexes, orphan pages, missing alt text, config assetsinfo/warning✅ Yes
Z5xxContent QualityPlaceholder text, short content, snippet validation, regressionswarning/error✅ Yes
Z6xxGovernanceBrand obsolescence, translation parity (opt-in)warning✅ Yes
Z9xxEngine & SystemRule execution errors, timeouts, system-level diagnosticserror/warning✅ Yes
Per-line suppression syntax

Suppress a finding on a specific line with a format-aware comment on that same line.
Markdown (.md): <!-- zenzic:ignore: Zxxx -->
MDX (.mdx): {/* zenzic:ignore: Zxxx */}
See Suppression Policy for the full reference.

Exit Code Contract

Exit CodeMeaningSuppressible?
0All checks passed (or suppressed via --exit-zero)
1Errors and warnings detected; use --strict to promote warnings✅ Yes
2Security breaches (Z201, Z204). Never suppressed❌ Never
3Security incidents (Z203 PATH_TRAVERSAL_FATAL). Never suppressed, even with --exit-zero❌ Never

Z0xx — Migration & Compatibility

Z000: UNSUPPORTED_ENGINE

Severity: error (fatal abort) · Penalty: none · Exit: 1 · Suppressible: No

Fatal configuration error: the adapter factory encountered a deprecated or removed engine alias in .zenzic.toml. Execution stops before any scan begins — Z000 does not appear in --format json output.

Fix:

  1. Open .zenzic.toml and set engine = "standalone" (or "mkdocs", "docusaurus", "zensical").
  2. Remove any legacy engine alias.

Z101: LINK_BROKEN

Severity: error · Penalty: −8.0 pts (Structural) · Exit: 1 · Suppressible: Yes · ↗ Gallery

A relative link points to a resource not found in the Virtual Site Map. The file may be outside docs_dir scope or matched by an exclusion rule.

Fix:

  1. Verify the physical file exists.
  2. Correct the relative path (e.g. ../folder/target.md).
  3. Confirm the file is not matched by ignored_patterns in config.

Z102: ANCHOR_MISSING

Severity: error · Penalty: −5.0 pts (Structural) · Exit: 1 · Suppressible: Yes · ↗ Gallery

The link target file exists (Z101 passes), but the specific HTML anchor (e.g. #setup) is absent from the target file's header registry. Zenzic parses all headings and explicit <a id="..."> tags during Pass 1.

Fix:

  1. Check the target file's heading text and verify the anchor slug.
  2. Ensure Kebab-case slugification matches the Markdown engine (Docusaurus: lowercase, spaces → hyphens).
  3. Use {#id} or <a id="id"></a> for custom IDs.

Z103: ORPHAN_LINK

Severity: error · Penalty: 0.0 pts · Exit: 1 · Suppressible: Yes · ↗ Gallery

The link target exists in the VSM but is not reachable through any navigation structure (sidebar/nav). Users can reach it only by direct URL.

Fix:

  1. Add the file to nav (MkDocs) or sidebars.ts (Docusaurus).
  2. If the hidden page is intentional, suppress with <!-- zenzic:ignore: Z103 -->.

Z104: FILE_NOT_FOUND

Severity: error · Penalty: −8.0 pts (Structural) · Exit: 1 · Suppressible: Yes

Low-level filesystem error: the engine could not open a file referenced by a link. Also fires as a slug-mismatch variant in Docusaurus: an absolute link targets a project-owned route prefix (e.g. /blog/) but the exact slug does not exist in the VSM — the most common cause is a slug: frontmatter field that differs from the URL used in the link.

blog/post.mdx:12: '/blog/zenzic-v070' not found in the site map
💡 Did you mean: '/blog/zenzic-v070-release/'?

Fix:

  1. Verify no concurrent process is modifying docs/ during the scan.
  2. Check docs_dir is correct and the file path is absolute relative to the repo root.
  3. (Slug-mismatch) Run zenzic inspect routes --kind physical to list all canonical slugs in the VSM. Update the link to match the exact frontmatter slug:.

Z105: ABSOLUTE_PATH

Severity: error · Penalty: −2.0 pts (Structural) · Exit: 1 · Suppressible: Yes · ↗ Gallery

An absolute filesystem path (e.g. C:\Docs\page.md or /home/user/docs/page.md) breaks documentation portability. Project-owned URL prefixes (/blog/, /docs/) are exempt from Z105 but still checked via VSM lookup (a missing slug raises Z104 instead).

Fix:

  1. Convert to a relative path from the current file's directory.
  2. Use @site/ or engine-specific aliases where supported.
  3. If you received Z104 on an absolute /blog/ link, see Z104 remediation above.

Z106: CIRCULAR_LINK

Severity: info · Penalty: 0.0 pts · Exit: 0 · Suppressible: Yes (informational only, --show-info)

A set of links forms a directed cycle (A → B → A). This is a structural telemetry signal — it does not block the Quality Gate or reduce the DQS.

Fix: Review the content flow; consider replacing one link with a "See Also" section. No action required if the cycle is intentional.

Z107: CIRCULAR_ANCHOR

Severity: warning · Penalty: −1.0 pt (Structural) · Exit: 1 · Suppressible: Yes

A link of the form [text](#anchor) resolves to a heading on the same page — a self-loop that navigates the reader to exactly where they already are. Distinct from a ToC entry (which links forward to a lower anchor on a long page).

Fix:

  1. Replace [text](#anchor) with plain prose if no navigation is intended.
  2. Or link to the concept on a different page.

Z108: EMPTY_LINK_TEXT

Severity: error · Penalty: −1.0 pt (Structural) · Exit: 1 · Suppressible: Yes · ↗ Gallery

Inline Markdown link or collapsed reference link has empty or whitespace-only visible text — e.g. [](./page.md), [ ](./page.md), [][ref]. Breaks screen reader accessibility and semantic indexing simultaneously.

Fix:

  1. Add descriptive link text: [Documentation](./page.md).
  2. Remove the link entirely if the destination is not yet known.

Z109: EXTERNAL_LINK_BROKEN

Severity: error · Penalty: −3.0 pt (Structural) · Exit: 1 · Suppressible: Yes · ↗ Gallery

An external URL returned an HTTP error status code (e.g. 404, 500) or was completely unreachable due to a connection timeout or DNS resolution failure during scan.

Fix:

  1. Check the target URL in a web browser.
  2. Correct the URL if misspelled, or remove the link if the destination has ceased to exist.

Z2xx — Security (credential scanner)

Z201: CREDENTIAL_SECRET

🔒 INVIOLABLE — Cannot be suppressed | Exit 2 | DQS collapses to 0/100

zenzic:ignore: Z201 is silently rejected. The credential scanner fires unconditionally on every line. ↗ Gallery

Severity: security_breach · Penalty: DQS collapses to 0/100 · Exit: 2

The credential scanner uses deterministic pattern matching (e.g., RE2) to detect known structural secrets (like AWS keys or GitHub tokens) without exponential backtracking, rather than relying on high-noise entropy checks. Speculative Base64 decoding is also applied — encoded tokens that decode to credential patterns are flagged.

Fix:

  1. IMMEDIATE: Rotate the leaked credential — it is compromised.
  2. Remove the secret from the file.
  3. Purge the git history using git-filter-repo.
  4. Use placeholders such as YOUR_API_KEY in documentation examples.

Z202: PATH_TRAVERSAL

🔒 INVIOLABLE — Cannot be suppressed | Exit 1 | DQS collapses to 0/100

zenzic:ignore: Z202 is silently rejected. ↗ Gallery

Severity: error · Penalty: DQS collapses to 0/100 · Exit: 1

The Path Traversal Guard intercepts any relative links attempting to escape the documentation root (e.g. ../.env). A relative path uses .. segments to escape the docs/ boundary, potentially exposing private repository files.

Fix:

  1. Move the target asset into the docs/ or static/ hierarchy.
  2. If you must reference an external file, use a symbolic link (if permitted) or a literal absolute URL.

Z203: PATH_TRAVERSAL_FATAL

🔒 INVIOLABLE — Cannot be suppressed | Exit 3 (highest) | DQS collapses to 0/100

zenzic:ignore: Z203 is silently rejected. Distinct from Z202: targets OS directories (/etc/, /root/) signalling supply-chain compromise.

Severity: security_incident · Penalty: DQS collapses to 0/100 · Exit: 3

Path traversal detected targeting restricted OS directories (e.g. /etc/, /root/). Cannot result from a legitimate documentation workflow — presence indicates template injection, a compromised toolchain, or a malicious commit.

Fix:

  1. Investigate the source file for malicious intent or supply-chain compromise.
  2. Remove all absolute paths referencing host-system locations.
  3. Audit your CI pipeline for injection vectors.

Z204: FORBIDDEN_TERM

🔒 INVIOLABLE — Cannot be suppressed | Exit 2 | DQS collapses to 0/100

zenzic:ignore: Z204 is silently rejected. Source: forbidden_patterns in .zenzic.local.toml (git-ignored). ↗ Gallery

Severity: security_breach · Penalty: DQS collapses to 0/100 · Exit: 2

The Privacy Gate detected a confidential project term (internal code-name, staging hostname, team alias) configured in .zenzic.local.toml. Matching is case-insensitive verbatim substring — no regex. Run zenzic init to scaffold .zenzic.local.toml (auto-added to .gitignore).

Brand integrity — two layers
LayerSourceScopeSeverity
Z204 Privacy Gateforbidden_patterns in .zenzic.local.toml (git-ignored)Private terms — code-names, staging hostsExit 2 (Critical)
Z601 Brand Guard[governance].brand_obsolescence in .zenzic.tomlDeprecated brand termsExit 1 (Quality)

Fix:

  1. Remove or generalise the forbidden term.
  2. If the term is legitimately public, remove it from forbidden_patterns.
  3. Verify .zenzic.local.toml is in .gitignore.

Z3xx — Reference Integrity

Z301: DANGLING_REF

Severity: error · Penalty: −4.0 pts (Navigation) · Exit: 1 · Suppressible: Yes · ↗ Gallery

A reference-style link ([my link][ref]) exists but its definition ([ref]: http://...) is missing. Most renderers silently degrade the link to plain text. Ensure your Markdown formatter (like Prettier or Markdownlint) does not inadvertently remove unused reference definitions during an automated pass, which can cause downstream references to dangle.

Fix:

  1. Add the missing definition at the bottom of the Markdown file.
  2. Check for typos in the reference ID.

Z302: DEAD_DEF

Severity: warning · Penalty: −1.0 pt (Navigation) · Exit: 1 · Suppressible: Yes · ↗ Gallery

A reference definition exists but no link in the file uses it. Harmless for readers but creates maintenance debt.

Fix: Remove the unused definition, or update a link to use this reference.

Z303: DUPLICATE_DEF

Severity: warning · Penalty: −3.0 pts (Navigation) · Exit: 1 · Suppressible: Yes · ↗ Gallery

Multiple definitions exist for the same reference ID. CommonMark specifies that the first definition wins, but this ambiguity should be resolved for deterministic cross-engine rendering.

Fix: Ensure each reference ID has exactly one definition; consolidate duplicates into a single canonical reference.


Z4xx — Structure

Z401: MISSING_DIRECTORY_INDEX

Severity: info · Penalty: none (structural hint) · Exit: 0 · Suppressible: Yes

A documentation directory has no index.md or README.md. The directory URL may return 404 or a raw listing depending on the build engine.

Fix: Create index.md in the flagged directory with a brief section overview.

Z402: ORPHAN_PAGE

Severity: warning · Penalty: −4.0 pts (Navigation) · Exit: 1 · Suppressible: Yes · ↗ Gallery

A file exists in docs/ but is not reachable from any navigation menu. The documentation equivalent of dead code.

Fix:

  1. Add the file to nav (MkDocs) or sidebars.ts (Docusaurus).
  2. Delete the file if it is a leftover artifact.

Z403: MISSING_ALT

Severity: warning · Penalty: none (accessibility warning) · Exit: 1 · Suppressible: Yes · ↗ Gallery

An image has no alt text, degrading screen reader accessibility and SEO.

Fix: Add descriptive text: ![A description of the image](url). Avoid generic labels like "image" or "screenshot".

Z404: CONFIG_ASSET_MISSING

Severity: warning · Penalty: none (configuration integrity warning) · Exit: 1 · Suppressible: Yes

The build engine's main configuration (e.g. docusaurus.config.ts) references a logo or favicon that does not exist at the specified path. The failure is global: every page in every locale ships without the branding asset.

Fix:

  1. Check favicon: or logo.src: paths in your config file.
  2. Ensure the asset is physically present in static/ (Docusaurus) or docs/ (MkDocs).

Z405: UNUSED_ASSET

Severity: warning · Penalty: −3.0 pts (Governance) · Exit: 1 · Suppressible: Yes

An image or asset file in the repository is never referenced by any Markdown file. "Dark Assets" bloat the repository and build artifacts silently.

Fix:

  1. Delete the unused file.
  2. Or reference it in a documentation page where appropriate.

Z406: NAV_CONTRACT

Severity: error · Penalty: −2.0 pts (Governance) · Exit: 1 · Suppressible: Yes

A conflict between the physical file structure and the engine's navigation config. For MkDocs: a nav entry pointing to a path that no physical file activates. For Docusaurus: an extra.alternate link absent from the VSM.

Fix:

  1. Align the nav path in your config with the physical file path.
  2. Run zenzic check all to verify the fix across the VSM.

Z5xx — Content Quality

Z501: PLACEHOLDER

Severity: warning · Penalty: −2.0 pts (Content) · Exit: 1 · Suppressible: Yes · ↗ Gallery

Placeholder strings (TODO, FIXME, [INSERT IMAGE HERE]) committed to production documentation signal incomplete work.

Fix: Replace the placeholder with actual content, or remove it until the content is ready.

Z502: SHORT_CONTENT

Severity: warning · Penalty: −1.0 pt (Content) · Exit: 1 · Suppressible: Yes · ↗ Gallery

A page contains fewer than 50 words of rendered prose (frontmatter, MDX comments, and HTML comments excluded). A page below this threshold cannot contain the semantic components necessary to answer a reader's question.

Fix: Expand the page, or combine it with a related page.

Z503: SNIPPET_ERROR

Severity: error · Penalty: −10.0 pts (Content — highest single-occurrence penalty) · Exit: 1 · Suppressible: Yes · ↗ Gallery

The Snippet Guard identified a syntax error in a fenced code block marked with a language tag. The reported line number is absolute — relative to the source file, not to the start of the snippet.

Fix:

  1. Correct the syntax within the code block.
  2. For intentionally broken examples, use ```text to bypass validation.

Z505: UNTAGGED_CODE_BLOCK

Severity: warning · Penalty: −1.0 pt (Content) · Exit: 1 · Suppressible: Yes · ↗ Gallery

A fenced code block has no language specifier. Syntax highlighters, the Snippet Guard (Z503), and screen readers cannot process it. Docusaurus metadata (e.g. ```python title="file.py" showLineNumbers) is fully supported and never flagged.

Fix: Add a language tag: ```python, ```bash, ```toml. For display-only blocks, use ```text or ```plaintext.


Z6xx — Governance

Z601: BRAND_OBSOLESCENCE

Severity: warning · Penalty: −2.0 pts (Governance) + Escalation · Exit: 1 · Suppressible: Yes · ↗ Gallery

A deprecated release name or brand identifier appears in a scanned file. Configured via [governance].brand_obsolescence in .zenzic.toml. CHANGELOG files are exempt by default (obsolete_names_exclude_patterns).

Governance Escalation: Beyond 10 total Z6xx occurrences, an exponential multiplier applies: deduction × 2^(excess / 5), capped at the 25-pt tier ceiling.

Fix:

  1. Update the text to the active release name.
  2. For intentional historical references in .md: append <!-- zenzic:ignore: Z601 -->.
  3. For .mdx files: append {/* zenzic:ignore: Z601 */}.
  4. To exempt a file pattern entirely, add it to obsolete_names_exclude_patterns in .zenzic.toml.

Z602: I18N_PARITY

Severity: warning · Penalty: none (bilingual integrity check) · Exit: 1 · Suppressible: Yes · ↗ Gallery

A translation mirror is missing, or the frontmatter of a translated file diverges from the canonical base (sidebar_position, sidebar_label, title). Two locales with different frontmatter produce asymmetric navigation graphs.

Fix:

  1. Create the missing translation at i18n/<locale>/docusaurus-plugin-content-docs/current/<path>.
  2. Copy the base-language frontmatter block and translate the values — do not add or remove keys.
  3. For intentional asymmetry, suppress with {/* zenzic:ignore: Z602 */} on the frontmatter block.

Z9xx — Engine & System

Z901: RULE_ENGINE_ERROR

Severity: error · Penalty: none (system-level) · Exit: 1 · Suppressible: Yes

An unhandled exception in a core rule or plugin. Zenzic's fail-visible principle converts silent crashes into explicit Z901 findings so the partial result is auditable.

Fix: Check the CLI output for a Python traceback. Report the issue at https://github.com/PythonWoods/zenzic/issues.

Z902: RULE_TIMEOUT

Severity: error · Penalty: none (system-level) · Exit: 1 · Suppressible: Yes

A rule exceeded the execution time limit (default > 30s). Almost always caused by catastrophic backtracking in a custom regex — a ReDoS risk that can also silently disable a security gate.

Fix:

  1. Review custom regex patterns in .zenzic.toml.
  2. Simplify patterns: avoid nested quantifiers like (a+)+.
  3. Use non-backtracking alternatives where possible.

Z906: NO_FILES_FOUND

Severity: note · Penalty: none · Exit: 0 · Suppressible: Yes (informational)

No .md / .mdx files found in the resolved docs_root after all exclusion layers. Suppressed in machine-output formats (json, sarif).

Fix:

  1. Verify docs_dir in .zenzic.toml (or --docs-dir) points to the correct directory.
  2. If the directory is intentionally empty, Z906 can be safely ignored — it exits 0.

Reserved Codes (Inactive)

Runtime-inactive by contract

The codes in this section are defined in the Zenzic registry and reserved for engine implementations. They are not emitted at runtime and have no impact on the Deterministic Quality Score.

Z111: VIRTUAL_ROUTE_BROKEN

Severity: error (reserved) · Engine: Docusaurus

A link targets a virtual route URL (e.g. /blog/tags/react/) that was never generated because no blog post carries that tag value in tags: frontmatter. Distinct from Z101: the URL is structurally valid, but no content source activates it.

Fix: Add the tag to the relevant posts, or update the link to target a tag that is actually generated. For forward-looking links, suppress temporarily with {/* zenzic:ignore: Z111 */}.

Z113: AUTHOR_KEY_COLLISION

Severity: error (reserved) · Engine: Docusaurus

Two or more authors.yml files declare the same author key. Docusaurus merges silently by priority, creating a hidden configuration dependency.

Fix: Identify the colliding key, keep the canonical definition, rename the duplicate, and update all blog posts that reference the renamed key.

Z114: LARGE_PAGINATION_SET

Severity: info (reserved) · Engine: Docusaurus

The blog plugin would generate more than 200 paginated index pages. Informational — not blocking.

Fix: Increase postsPerPage in docusaurus.config.ts or enable archiveBasePath to offload historical posts.

Z504: QUALITY_REGRESSION

Severity: warning (reserved)

Emitted by zenzic diff when the current DQS is lower than the saved baseline (.zenzic-score.json). Not itself weighted into the score (that would be circular); it identifies which commit introduced a regression.

Fix: Run zenzic score to see the breakdown by category, fix the underlying findings that caused the drop, then run zenzic score --save on main to update the baseline.


Historical Code Remap

Deprecated CodeActive CodeNotes
Z903Z405Canonical remap for UNUSED_ASSET.
Z904Z406Canonical remap for NAV_CONTRACT.
Z905Z601Canonical remap for BRAND_OBSOLESCENCE.
Z907Z602Canonical remap for I18N_PARITY.

Historical identifiers remain valid only as historical references in migration prose. Active findings and section anchors always use the canonical codes listed in this matrix.


Suppressing Diagnostics

See Suppression Policy for inline suppression syntax (zenzic:ignore), the Suppression Debt model, and the --audit override.