Skip to content

Troubleshooting Validation ​

./hooks/validate.sh is the deterministic schema check described in Validation & Linting. It enforces _meta/schemas/frontmatter.yaml and reads the allowed values from _meta/wiki.config.yaml. When something is wrong it prints one line per problem, then a summary, and exits with status 1:

wiki/concepts/example.md: missing required field 'summary'
wiki/concepts/example.md: tag 'quantum' not in config domains (expected: general)
Validation failed: 2 issue(s)

Each line has the shape <file>: <message>. This page lists the messages you are most likely to see, the rule behind each one, and how to fix it. Every message and rule here comes from hooks/validate.sh and _meta/schemas/frontmatter.yaml.

OutputMeaning
OK: <N> files validatedEvery checked file passed. Exit status 0.
Validation failed: <N> issue(s)At least one problem was listed above this line. Exit status 1.

To re-check a single file while fixing it, pass its repository-relative path:

bash
./hooks/validate.sh wiki/concepts/example.md
./hooks/validate.sh --staged     # staged .md files under wiki/ and raw/
./hooks/validate.sh --all        # every .md under wiki/ and raw/
./hooks/validate.sh --json --all # same problems as one JSON object

Run the script from inside the repository (it locates the root with git rev-parse --show-toplevel, or ECHO_WIKI_ROOT if set).

Which rules apply to a file ​

The script picks a rule set ("zone") from the file's path. Knowing the zone tells you which messages can appear.

ZonePathChecks that run
KB articlewiki/<entity dir>/ (directories from entity_types in config; default concepts/, people/, tools/, sources/)Frontmatter shape, 11 required fields, enums, dates, tags, sources, type-specific fields, filename, wikilinks, evidence locators
Raw sourceraw/Frontmatter shape, 8 required fields, source_type and ingestion_tool enums, dates, tags, filename, at least one visible heading
Workspace filewiki/workspaces/Frontmatter shape, title and created, created date, wikilinks. Evidence locators only under knowledge-maintenance/context/ and <actor>/answers/

wiki/_index.md, wiki/_backlinks.md, wiki/_log.md, .gitkeep files and anything under wiki/.obsidian/ are never validated.

Commit blocked by the pre-commit hook ​

hooks/pre-commit.sh runs on every git commit once it is installed as .git/hooks/pre-commit (see Pre-commit Hook for the install command). It copies the staged snapshot (every file in the Git index) into a temporary directory and runs validate.sh --all against that copy. That means it checks:

  • every .md file under wiki/ and raw/ in the snapshot, including files already committed, not only the files in this commit;
  • the staged version of each file, not the version on disk;
  • the staged _meta/wiki.config.yaml, so allowed tags, types and directories come from the same snapshot.

When validation fails, the hook prints every line validate.sh produced, each prefixed with -, and blocks the commit:

Pre-commit validation failed:

  - wiki/concepts/example.md: missing required field 'summary'
  - wiki/concepts/example.md: tag 'quantum' not in config domains (expected: general)
  - Validation failed: 2 issue(s)

Fix errors or use 'git commit --no-verify' for WIP commits.

The listed lines are the same messages described on this page; look each one up in its section. NOTE: lines can appear in the list as well; they are not failures. The last line names a Git option that bypasses the hook; this page does not use it. Fix the files instead.

OutputMeaningFix
Pre-commit validation failed: followed by a listThe staged snapshot has at least one validation problem. The commit was not made.Fix every listed problem, stage the files and commit again (steps below).
Pre-commit validation failed: could not materialize the staged snapshot.Git could not copy the staged files into a temporary directory, so nothing was validated. The commit was not made.Read the Git error printed above this line, fix its cause, and commit again.
Pre-commit validation passedEvery file in the staged snapshot passed.Nothing to do; the commit goes ahead.

To fix the files and commit again:

  1. Fix each file named in the list.
  2. Stage the fixes with git add <file>. The hook only sees staged content, so a fix that is saved but not staged still fails.
  3. Optionally re-check with ./hooks/validate.sh --all. It reads the files on disk, so it agrees with the hook only when every change is staged.
  4. Run git commit again. The hook re-runs on the new snapshot.

Common surprises:

  • A file you did not change is listed. The hook checks the whole snapshot, so an invalid file that is already committed blocks every commit. Fix and stage that file too.
  • structure: lines for paths that exist on disk. The snapshot holds only what Git tracks, so a file such as wiki/_index.md that was never added counts as missing. Stage it.

Why did validation skip a file? ​

The script prints a note on standard error for Markdown files it cannot classify, and does not count them as validated. These notes are not failures: the file is simply not checked.

MessageWhy it firesFix
NOTE: not a KB or workspace path, skipping: <path>The file is under wiki/ but not inside a configured entity directory or wiki/workspaces/.Move it into a configured directory or a workspace, or add the entity type to _meta/wiki.config.yaml.
NOTE: outside wiki/ and raw/, skipping: <path>The file is outside both validated zones.Only files under wiki/ and raw/ are validated.

Why does validation report a structure error? ​

These lines start with structure: instead of a file path. They are checked before any file and usually mean the repository layout is incomplete.

MessageWhy it firesFix
invalid _meta/wiki.config.yamlThe config is not valid YAML, has no non-empty entity_types list, or an entity type lacks name, dir or label, or two entries share a name or dir.Repair the config; see Configuration.
repository root path must be a real directory: <path>_meta, raw or wiki is missing at the repository root or is a symlink.Create the directory, or replace the symlink with a real directory.
required path missing: <path>wiki/_index.md, wiki/_backlinks.md, wiki/workspaces/ or a configured KB directory does not exist.Run ./hooks/reindex.sh to regenerate the two index files; create missing directories.
unsafe configured KB directory: <dir>An entity type's dir is not a single kebab-case path component, or is the reserved name workspaces.Use a plain lowercase name such as decisions.
configured KB directory must be a real direct child: wiki/<dir>The configured KB directory is a symlink or otherwise not a real directory directly under wiki/.Replace it with a real directory.
managed path may not be a symlinkA symlink exists somewhere under wiki/ or raw/, or a path passed on the command line is a symlink.Replace the symlink with a real file or directory.
path not foundA path passed on the command line does not exist.Check the spelling; paths are relative to the repository root.

Why does validation say a date format is invalid? ​

MessageWhy it firesFix
invalid date format in '<field>' (expected YYYY-MM-DD, got '<value>')A date field is not four digits, a hyphen, two digits, a hyphen, two digits. Only the shape is checked.Write dates as 2026-04-04, quoted or unquoted. Values such as 04/04/2026 or April 4, 2026 fail.

Date fields that are checked: created, last_updated and last_verified in KB articles (plus source_date for source-summary); source_date and ingested in raw sources; created in workspace files.

Why does validation say a field value is invalid? ​

Enum fields must match one of the allowed values exactly. Matching is exact and case-sensitive; the built-in values are all lowercase.

MessageWhereFix
invalid type '<value>' (expected: <entity type names>)KB articleUse a name from entity_types in _meta/wiki.config.yaml (default concept, person, tool, source-summary). A common slip is using the directory (concepts) or the label (Concepts) instead of the name.
invalid decay_rate '<value>' (expected: fast|medium|slow)KB articleUse fast, medium or slow.
invalid confidence '<value>' (expected: high|medium|speculative)KB articleUse high, medium or speculative.
invalid category '<value>' (expected: framework|platform|service|product)KB article with type: toolUse framework, platform, service or product.
invalid source_type '<value>' (expected: <source types>)Raw source, and KB article with type: source-summaryUse a value from source_types in _meta/wiki.config.yaml (default internal, blog, paper, tweet, substack, github, podcast, video). To allow a new type, add it to the config and to the source_type lists in _meta/schemas/frontmatter.yaml.
invalid ingestion_tool '<value>' (expected: tavily|firecrawl|local)Raw sourceUse tavily, firecrawl or local.

Why does validation say a filename is not kebab-case? ​

MessageWhy it firesFix
filename not kebab-case (expected: lowercase-with-hyphens.md)The file name does not match ^[a-z0-9]+(-[a-z0-9]+)*\.md$: only lowercase letters a–z, digits and single hyphens, ending in .md. Uppercase letters, underscores, spaces, extra dots, and leading, trailing or doubled hyphens all fail.Rename the file, for example Bad_Name.md to bad-name.md. Then update any wikilink that pointed at the old name and run ./hooks/reindex.sh.
filename exceeds 60 charactersThe file name, including .md, is longer than 60 characters.Shorten the name and fix wikilinks as above.

Filenames are checked in KB articles and raw sources, not in workspace files.

Why does validation say a required field is missing? ​

MessageWhy it firesFix
missing required field '<field>'A key the zone requires is absent from the frontmatter. The check looks for the key, so a key that is present with an empty value passes this check (and may fail a later one).Add the key. Required keys per zone are listed below.
missing type-specific field '<field>' for type '<type>'A KB article whose type is one of the built-in types lacks a field that type requires. Custom entity types have no type-specific requirements.Add the field listed for that type below.

Required keys by zone:

ZoneRequired keys
KB articletitle, type, created, last_updated, last_verified, decay_rate, confidence, tags, sources, related, summary
Raw sourcetitle, source_url, source_type, source_date, author, ingested, ingestion_tool, tags
Workspace filetitle, created

Type-specific keys for built-in KB types:

TypeExtra required keys
conceptdomain
personrole
toolcategory, maintained
source-summarysource_url, source_type, author, source_date

See Frontmatter Schema for complete examples of each zone.

Why does validation say a source path does not exist? ​

The sources list in a KB article holds plain strings, not wikilinks. Each entry is a path from the repository root to a file inside raw/, such as raw/blogs/post.md.

MessageWhy it firesFix
sources list is emptyThe sources key exists but has no entries (sources: []).List at least one raw file.
source path does not exist: <path>No file exists at that path from the repository root. Common causes: wikilink syntax ([[raw/blogs/post]]), a missing .md, a path relative to wiki/ instead of the root, a typo, or a raw file that was removed.Use the exact path of an existing file under raw/, including .md. If the raw file was deleted on purpose, run /rebuild so the article is regenerated from the remaining sources.
source path escapes raw/: <path>The file exists but is not inside raw/: the path uses .., points elsewhere, or goes through a symlink that leaves raw/.Cite only files that live under raw/.

Why does validation say a tag is not in config domains? ​

MessageWhy it firesFix
tag '<tag>' not in config domains (expected: <domains>)A value in tags does not equal the name of a domain under domains: in _meta/wiki.config.yaml. The default config defines only general. Matching is against name, not label, and is case-sensitive.Change the tag to a configured domain name, or add the domain to the config (see Configuration).

Tags are checked in KB articles and raw sources, not in workspace files. If domains: in the config is empty, any tag is accepted.

Every [[...]] in a KB article or workspace file is checked, both in the frontmatter (such as related) and in the visible body. The script drops any display text after | and any anchor after #, then expects the file wiki/<target>.md to exist.

MessageWhy it firesFix
broken wikilink [[<target>]]wiki/<target>.md does not exist. Common causes: the type directory is missing ([[event-sourcing]] instead of [[concepts/event-sourcing]]), the link includes .md, the directory or name is misspelled, the target article has not been compiled yet, or a wikilink was used where a plain path belongs (for example in sources).Write links vault-relative from wiki/, with the directory and without .md: [[concepts/event-sourcing|Event Sourcing]]. Create or compile the missing target, or remove the link.
wikilink escapes wiki/: [[<target>]]The target starts with /, contains ../ or ./, or resolves through a symlink to a file outside wiki/.Use a plain path relative to wiki/, such as concepts/name.

Wikilinks inside fenced code blocks and HTML comments in the body are not checked; wikilinks in the frontmatter always are. Raw sources are not checked for wikilinks.

Why does validation say an evidence locator is missing or invalid? ​

KB articles, context packs under wiki/workspaces/knowledge-maintenance/context/, and files under wiki/workspaces/<actor>/answers/ must contain at least one visible line of the form Evidence: raw/<path>.md#<exact heading>. Lines inside fenced code blocks, HTML comments or raw HTML blocks do not count.

MessageWhy it firesFix
missing evidence locatorNo visible Evidence: line was found in the body.Add Evidence: raw/<path>.md#<heading> after the paragraph it supports.
invalid evidence locator '<line>' (expected: Evidence: raw/<path>.md#<exact heading>)The locator does not start with raw/, does not end in .md before the #, or has nothing after the #.Match the shape exactly.
evidence source does not exist: <path>The raw file named before the # is missing.Point at an existing raw file.
evidence source escapes raw/: <path>The path leaves raw/ through .., ./ or a symlink.Cite only files under raw/.
evidence source not listed in sources: <path>In a KB article, the cited raw file is not in the frontmatter sources list.Add the raw path to sources.
evidence heading does not exist: <path>#<heading>The raw file has no visible Markdown heading with exactly that text. Headings inside code fences, HTML comments or the raw file's frontmatter do not count.Copy the heading text exactly from the raw file, without the leading # marks.
missing citable Markdown headingA raw source has no visible Markdown heading, so nothing in it can be cited.Add a heading such as ## Content before the body. See Upgrading an Existing Wiki.

Why does validation say the frontmatter is missing or invalid? ​

If the frontmatter block cannot be read, the script reports one of these messages and skips every other check for that file. Fix it, re-run, and the remaining problems for that file will appear.

MessageWhy it firesFix
missing frontmatterLine 1 of the file is not exactly ---.Start the file with --- on the very first line, with nothing before it (no blank line, no byte-order mark).
unclosed frontmatterThe file has fewer than two lines that are exactly ---.Add the closing --- line after the last field.
invalid frontmatter syntaxThe text between the markers is not valid YAML, is not a key/value mapping, or a key or value contains a control character. Typical causes: a stray prose line inside the block, an unclosed quote (title: "Unclosed), an invalid backslash escape inside double quotes ("Invalid \q escape"), or a malformed list (tags: [ai,, software]).Use one key: value per line. Close every quote and bracket, quote strings that contain : or #, and write lists as ["a", "b"]. Keep wikilinks in related quoted, as in the schema examples.
YAML parser unavailable (ruby is required)The ruby command is not on PATH. The script parses YAML with Ruby's standard library and needs no gems.Install Ruby or add it to PATH.

After fixing ​

Re-run ./hooks/validate.sh on the file, then ./hooks/validate.sh --all before committing. If the pre-commit hook is installed it runs the full check for you and blocks the commit until it passes. For problems a script cannot see, such as contradictions or stale content, run /lint.

Released under the MIT License.