YAML Schema ValidatorA VS Code extension (TypeScript) that validates YAML configuration files
against a schema, a JSON Schema (2020-12) written in YAML, next to them
or declared in their first line. It follows
Schema files themselves are checked against a built-in meta-schema, so you get completion, hover help and errors while writing schemas as well. InstallationDownload
Every build on GitHub Actions also keeps the Quick start
The first line of A complete example lives in Declaring the schema in the first lineInstead of a sibling
Includes (
|
| Keywords | |
|---|---|
type |
string, number, integer, boolean, object, array, null, or a list of them |
enum, const |
Allowed values |
minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf |
Numbers |
minLength, maxLength, pattern, format |
Strings. Checked formats: date-time, date, time, email, hostname, ipv4, ipv6, uri, uri-reference, json-pointer, regex |
prefixItems, items, minItems, maxItems, uniqueItems, contains, minContains, maxContains, unevaluatedItems |
Arrays |
properties, patternProperties, additionalProperties, required, propertyNames, minProperties, maxProperties, dependentRequired, dependentSchemas, unevaluatedProperties |
Objects |
allOf, anyOf, oneOf, not, if / then / else |
Combinations |
$ref, $defs, $anchor |
#/$defs/x, any JSON pointer, #anchor, other.schema.yml or other.schema.yml#/$defs/x ($dynamicRef is resolved like $ref) |
true / false |
Boolean schemas (legacyKey: false forbids a key) |
title, description, default, examples, deprecated, $comment, $schema, $id |
Documentation, used by hover and completion |
unevaluatedProperties: false reports keys that no keyword evaluated, including
keys declared in allOf, anyOf, oneOf, if / then / else or a $ref;
additionalProperties: false only sees the properties next to it.
Older schemas keep working: with $schema: "http://json-schema.org/draft-07/schema#"
(or 2019-09) the draft-07 forms definitions, dependencies, items: [...] +
additionalItems are understood (they are accepted in 2020-12 schemas as well).
The only difference in behaviour is $ref: since 2019-09 keywords next to a
$ref apply too, in draft-07 they only add documentation and messages.
As in JSON Schema, keys that are not listed are allowed unless
additionalProperties: false is set. For keys whose names are free but whose
content follows one structure, use additionalProperties (or
patternProperties) with a schema.
Extensions
These keywords are ignored by standard JSON Schema validators. The first group is also understood by VS Code and Red Hat YAML:
| Keyword | |
|---|---|
errorMessage |
Message (text) for every problem of this schema |
patternErrorMessage |
Message when pattern does not match |
markdownDescription |
Help text in Markdown (preferred over description in hover) |
deprecationMessage |
Marks the key as deprecated with this reason (deprecated: true works too); reported as a warning with strike-through |
defaultSnippets |
Completion snippets: [{label, body}] or [{label, bodyText}] |
x-errorMessages |
Message templates per keyword, e.g. {minimum: "...", required: "..."}; override errorMessage |
x-severity |
error / warning / info / hint, or a map per keyword ({additionalProperties: error}) |
x-see |
Files attached to every problem as clickable locations: docs/a.md:12, docs/a.md#L12 or {file, line, label} (or a list) |
Any other x-… keyword is accepted and ignored.
Message placeholders
Problem kinds (the keys of x-errorMessages / x-severity) are the keyword
names: type, required, additionalProperties (unknown key), enum, const,
pattern, format, minimum, maximum, exclusiveMinimum,
exclusiveMaximum, multipleOf, minLength, maxLength, minItems,
maxItems, uniqueItems, contains, maxContains, additionalItems (items: false),
unevaluatedItems, minProperties, maxProperties, propertyNames, dependentRequired,
unevaluatedProperties, anyOf, oneOf, not,
false, deprecated. A message for required can be written on the object or
on the required property itself.
Placeholders: ${key}, ${path}, ${value}, ${actual}, ${expected},
${allowed}, ${hint}, ${parent} (the object a missing / unknown key belongs
to), ${file}, ${line} (location of the problem), ${schema}, ${ruleLine}
(location of the rule), ${title}, ${description}, ${default}, ${const},
${format}, the keyword values (${minimum}, ${maxLength}, ${pattern}, ...),
plus ${count} (number of items / keys), ${length} (string length),
${reason} (deprecation), ${dependency} and ${missing} (dependentRequired).
Red Hat YAML shows errorMessage / patternErrorMessage verbatim, without filling in
placeholders. Put messages with placeholders into x-errorMessages; Red Hat
ignores those and shows its own text.
Each diagnostic's code (e.g. pattern) links to the rule in the schema, and the
problem details list the rule, x-see files and the include chain as clickable
locations.
Red Hat YAML as backup
Schema files are valid JSON Schemas (2020-12 is supported by Red Hat YAML), so the Red Hat YAML extension (and
other tools built on yaml-language-server, or any JSON Schema validator after
converting the YAML) can validate with them:
- Associate the files with the modeline in the first line
(
# yaml-language-server: $schema=app.schema.yml, written by YAML Schema: Add Red Hat YAML Modeline) or with Red Hat'syaml.schemassetting. Red Hat does not know thename.schema.ymlnaming convention. - Red Hat does not resolve
extends: it validates every file on its own.- Declare
extendsin the schema (extends: {type: [string, array]}) whenadditionalProperties: falseis used. - Keys that only come from included files are reported as missing there.
- Prefer
key:+extends: file.ymloverkey: !extends file.yml, because Red Hat sees the tag form as a string. The modeline command adds!extendstoyaml.customTags, so the tag itself is accepted.
- Declare
- When both extensions are active, both report problems. Set
"yaml.validate": falsein the workspace to keep Red Hat for completion only.
Anchors and aliases
- An anchor (
&name) that no alias (*name) uses is shown greyed out, with "Anchor '&name' is never used" on hover (disable withyamlSchema.unusedAnchors). - Hovering over
&nameshows the anchored content and the lines that use it; hovering over*nameshows the content it stands for and where the anchor is. - Go to Definition on an alias jumps to its anchor, Find All References on either lists the anchor and all its aliases.
Commands and settings
| Command | |
|---|---|
YAML Schema: Revalidate All Files |
Rescan the workspace and validate everything |
YAML Schema: Open Schema for Current File |
Open the schema (or the validated file from a schema). Offers to generate a starter schema from the file's content when none exists. Also available by clicking the status bar item |
YAML Schema: Add Red Hat YAML Modeline |
Write # yaml-language-server: $schema=… as the first line of the current file |
Settings were named yamlScheme.* before 0.7.0; values set under the old names
are still used.
| Setting | Default | |
|---|---|---|
yamlSchema.extendKeyword |
extends |
Include keyword; the tag form uses the same word (!extends) |
yamlSchema.schemaInfix |
schema |
Schema files are named name.<infix>.yml |
yamlSchema.unknownKeySeverity |
warning |
Severity of keys forbidden by additionalProperties: false (ignore to disable) |
yamlSchema.includeSummary |
true |
Summary diagnostic on extends lines |
yamlSchema.unusedAnchors |
true |
Grey out anchors that no alias uses |
yamlSchema.debounceMs |
250 |
Delay before revalidating |
yamlSchema.exclude |
**/{node_modules,.git}/** |
Ignored when searching for schemas |
YAML support
Parsing is done by the yaml package (YAML 1.2,
bundled into the extension, so nothing has to be installed). Anchors, aliases,
tags and the merge key << are supported. Only the first document of a file is
validated. Values are typed with the YAML 1.2 core schema (yes is a string,
1.2 is a number, so quote versions). As in JSON Schema, 1.0 counts as an
integer.
Development
npm install
npm run bundle # esbuild → dist/extension.js (the `yaml` package is inlined)
npm run typecheck
npm test # tsc → out/, unit tests with node:test
npm run package # vsce package (runs a minified bundle first)
Versions: every change gets the next development version and a git tag, e.g.
0.4.0 → 0.5.0-devel.1 → 0.5.0-devel.2. npm run bump -- patch|minor|major
computes it (a bigger change raises the upcoming release: 0.4.1-devel.3 + minor
→ 0.5.0-devel.1) and keeps the ## 0.5.0 (in development) heading of
CHANGELOG.md in sync. Development tags (v0.5.0-devel.2) are built by GitHub
Actions (the .vsix is a build artifact) but not released.
Releases are made by hand: npm run bump -- release (turns 0.5.0-devel.2 into
0.5.0 and the changelog heading into ## 0.5.0), commit, then push the tag
v0.5.0. The workflow in .github/workflows/build.yml builds the .vsix and
publishes a GitHub release with it.
All packages are dev dependencies: the published extension is a single bundled
file without node_modules. Open the repository in VS Code and press
F5 to bundle and start an Extension Development Host with the
example folder.
Source layout: src/core/ contains the editor independent parts (YAML adapter
around the yaml package, include resolver, schema compiler, validator,
completion / hover logic) and is covered by the tests in src/test/;
src/manager.ts tracks files and diagnostics; src/providers.ts adapts the
core to the VS Code API.