TOML Schema

TOML Schema Specification

TOML Schema is a set of TOML-based constructs that define the structure, the names, and the types of configuration data on a TOML file.

TOML Schema validates the parsed input of a TOML file to:

  1. Eliminate or reduce misconfiguration that could potentially damage if only validated during production evaluation,
  2. Be leveraged by editors and other tools to provide and enrich auto-completion and code hints for validation on the fly.

The schema format follows the TOML specification, meaning that a TOML Schema is in itself a valid TOML document.

Conformance Terminology

The key words MUST, MUST NOT, REQUIRED, SHOULD, SHOULD NOT, and MAY in this document are to be interpreted as described in BCP 14 when, and only when, they appear in all capitals.

A schema loader parses a TOML Schema document and rejects malformed schemas. A validator applies a successfully loaded schema to a TOML document. An implementation may provide both components in one API or command.

Table of Contents

First Glance

TOML example

Let's look at the TOML example displayed on the front page of toml.io:

# This is a TOML document

title = "TOML Example"

[owner]
name = "Tom Preston-Werner"
dob = 1979-05-27T07:32:00-08:00

[database]
enabled = true
ports = [ 8000, 8001, 8002 ]
data = [ ["delta", "phi"], [3.14] ]
temp_targets = { cpu = 79.5, case = 72.0 }

[servers]

[servers.alpha]
ip = "10.0.0.1"
role = "frontend"

[servers.beta]
ip = "10.0.0.2"
role = "backend"

TOML Schema example

Example of a TOML Schema that validates the TOML document above:

# This is a TOML Schema document
[toml-schema]
version = "1.0.0"

[types.serverType]
type="table"

    [types.serverType.ip]
    type="string"
    pattern='^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$'
    [types.serverType.role]
    type="string"

[elements.title]
type="string"

[elements.owner]
type="table"
    [elements.owner.name]
    type="string"
    [elements.owner.dob]
    type="offset-date-time"

[elements.database]
type="table"

    [elements.database.enabled]
    type = "boolean"
    [elements.database.ports]
    type = "array"
    itemtype = "integer"
    [elements.database.data]
    type = "array"
    itemtype = "array"
    [elements.database.temp_targets]
    type = "table"

[elements.servers]
type="collection"
itemtype = "types.serverType"
minlength = 1

Schema Structure Reference

A TOML Schema file has the following structure:

# Metadata
[toml-schema]

# Types
[types]

# Elements
[elements]

Top-level Structure Conditions

  • [toml-schema]: table with information and metadata of the schema.
    • Required
  • [types]: table with definitions of types to be reused in elements.
    • Optional
  • [elements]: table with the overall structure of the TOML document, its tables, properties, and conditions.
    • Required

No other top-level table or key-value pair MAY appear in a TOML Schema document.

Metadata Table - [toml-schema]

This table is reserved for metadata regarding the TOML Schema itself.

[toml-schema]
version = "1.0.0"
# custom = "value" # *NOT allowed

[toml-schema.meta]
<any> = <value> # allowed
...

[toml-schema.meta.subtable] # allowed

# [toml-schema.custom] # *NOT allowed
...

Supported Properties

  • version: the TOML Schema language version used by this schema document. Type: string.
    • Required.
  • toml-schema.meta: table reserved for any custom user-provided metadata.
    • Optional.

Custom properties and tables MUST NOT appear directly under toml-schema; they MAY appear only inside the toml-schema.meta table.

Schema Versioning

TOML Schema follows the same version-numbering policy as the TOML specification: schema language versions use Semantic Versioning.

The version property MUST be a string containing a complete Semantic Versioning 2.0.0 value. The MAJOR.MINOR.PATCH core is required; a valid pre-release suffix and build metadata are optional. The current TOML Schema version is 1.0.0.

[toml-schema]
version = "1.0.0"

Schema loaders MUST reject schema documents whose version is missing, is not a string, or is not a valid SemVer value. Shorthand values such as "1" and "1.0" are invalid.

An implementation that supports TOML Schema version MAJOR.MINOR.PATCH MUST accept schema documents with the same major version and a minor version less than or equal to the implementation's supported minor version. Patch versions, pre-release identifiers, and build metadata do not add schema-language features and do not affect compatibility. Schema loaders MUST reject schema documents with an unsupported major version or a greater minor version. Support for schema documents from an earlier major version is implementation-defined; an implementation MUST NOT treat support for a later major version as implicit support for an earlier one.

Elements table - [elements]

The [elements] table is the root schema for the TOML document being validated. Schema authors use it to describe the application data that may appear at the top level of the TOML document.

Each direct child of [elements] defines one top-level TOML key. Nested children define the structure below that key, such as fields inside a table or item definitions inside arrays and collections.

The root is closed: every top-level application-data key MUST be defined by a direct child of [elements]. Validators MUST reject any other top-level application-data key. This rule applies even when [elements] has no children, so an empty [elements] table accepts no application data.

The reserved root [toml-schema] metadata table is the only exception. When [elements.toml-schema] is omitted, validators ignore that table during application-data validation as described in TOML Reference of a TOML Schema. Therefore, a document validated by an empty [elements] table may contain only the reserved [toml-schema] table and no application data.

This root behavior differs from a nested property declared as type = "table" with no child definitions. Such a nested table is intentionally open-ended as described in Tables; an empty [elements] table is not an implicit allow-anything schema.

For example, this schema:

[elements.title]
type = "string"

[elements.database]
type = "table"

    [elements.database.enabled]
    type = "boolean"

validates a TOML document shaped like this:

title = "Example"

[database]
enabled = true

Use [elements] for document-specific keys. Use [types] for reusable definitions that can be referenced from [elements] or from other reusable types. Elements follow the same structure and validation rules as types, except that elements cannot reference other elements. To reuse conditions and structures, define them under [types] and reference them from [elements].

The companion toml-schema.tosd validates this top-level structure. It intentionally leaves individual schema-definition tables open: schema property names such as type and itemtype may also be target child keys, and TOML cannot represent both a key-value property and a child table with the same path in one self-schema definition. Schema loaders therefore enforce the vocabulary, property types, and conditional applicability rules specified below.

Types table - [types]

The [types] table is for use when there is a need for custom, reusable types of structure or properties. A type is referenced in an element or another type with a type reference.

Type references are strings accepted by type, itemtype, items, oneof, anyof, allof, then, and else. A type reference may be either:

  • a built-in type name such as "string", "boolean", or "integer";
  • a named reusable definition from [types], written either as "types.<typename>" or "<typename>".

Each reusable type is a direct child of [types], and its name is the exact decoded TOML key of that child. A dot in a type name is an ordinary character when the key is quoted, so [types."network.endpoint"] defines the reusable type named network.endpoint; it does not define a nested type hierarchy. Tables below a direct child define that type's fixed children.

The optional types. reference prefix is removed exactly once before lookup. Consequently, both "network.endpoint" and "types.network.endpoint" refer to the direct definition [types."network.endpoint"]. To keep those two forms unambiguous, a reusable type name MUST NOT begin with the literal characters types.. Built-in type names are also reserved and MUST NOT be used as [types] definition names. The reserved names are any, string, integer, float, boolean, offset-date-time, local-date-time, local-date, local-time, array, table, and collection.

Two built-in names have context-specific restrictions:

  • collection is valid for type only when the effective definition obtains an itemtype locally or from a compatible allof component. It MUST NOT be used as a bare reference in itemtype, items, oneof, anyof, allof, then, or else, because those locations cannot supply the collection's dynamic-value rule. Schema loaders MUST reject such references at schema-load time.
  • any is valid for type, itemtype, and items, but it MUST NOT appear directly in oneof, anyof, allof, then, or else. Schema loaders MUST reject a direct any component at schema-load time.

These restrictions apply to bare built-in references, not to named reusable definitions. A named definition that declares a complete collection or selects type = "any" remains a valid reference.

type, oneof, anyof, and the if/then/else triple are alternative ways to select the type of the current schema node. Every definition MUST declare exactly one selector, except that a definition with nested child definitions MAY omit all selectors and is then treated as type = "table". Schema loaders MUST reject a definition that combines selectors, contains only part of a conditional triple, or declares no selector and has no nested child definitions. type accepts either a built-in type name or a named reusable definition from [types]. Container member types are selected separately with itemtype: it validates each member of an array or each dynamically keyed value of a collection. itemtype requires the same definition to declare the built-in type = "array" or type = "collection"; it cannot be attached to another built-in or to a named type reference.

Nested child definitions are valid only when the current node selects the built-in table or collection type, or when the node omits a selector and is therefore an implicit table. Schema loaders MUST reject child definitions attached to a scalar, array, named type reference, oneof, anyof, or conditional node rather than silently ignoring them.

Every named reference used by type, itemtype, items, oneof, anyof, allof, then, or else MUST resolve to a definition in [types]. Schema loaders MUST reject unresolved references at schema-load time, including references in definitions that are optional or not exercised by the document being validated.

Type-selection and composition references MUST be acyclic. A cycle composed of named type aliases, oneof alternatives, anyof alternatives, conditional branches, or allof components cannot resolve to a concrete definition and schema loaders MUST reject it at schema-load time. Structural recursion through table or collection children, array itemtype, or tuple items remains valid because each recursive step consumes a nested document value.

[types]

[types.<typename>]
type = "<type-reference>"
description = "<human-readable description>"
itemtype = "<type-reference>"
items = [ "<type-reference>", ... ]
oneof = [ "<type-reference>", ... ]
anyof = [ "<type-reference>", ... ]
if = { key = "<direct-child-name>", equals = <toml-value> }
then = "types.<typename>"
else = "types.<typename>"
allof = [ "<type-reference>", ... ]
allowedvalues = [ <array-with-enumeration-of-allowed-values> ]
pattern = "<string-regex-for-string-validation>"
keypattern = "<string-regex-for-collection-key-validation>"
optional = true|false
min = <integer | float | offset-date-time | local-date-time | local-date | local-time>
max = <integer | float | offset-date-time | local-date-time | local-date | local-time>
minlength = <integer>
maxlength = <integer>
uniqueitems = true|false
dependentrequired = { <fixed-child> = [ "<fixed-child>", ... ], ... }
mutuallyexclusive = [ [ "<fixed-child>", "<fixed-child>", ... ], ... ]
exactlyone = [ [ "<fixed-child>", "<fixed-child>", ... ], ... ]
default = <toml-value>
deprecated = true|false

The following matrix summarizes where definition properties apply. The detailed sections below remain authoritative.

Property Applicable definition
type Selects one built-in or named type; mutually exclusive with other selectors
oneof, anyof Select the current node from one or more alternatives; mutually exclusive with other selectors
if, then, else Exhaustively select one of two named table-like definitions from a direct child's parsed value
allof Conjunctively applies one or more compatible type references in addition to the local definition
description, optional, default, deprecated Any definition, including a named reference or alternative selector
itemtype A definition with built-in type = "array" or type = "collection"
items A definition with built-in type = "array"; mutually exclusive with itemtype, allowedvalues, min, max, minlength, and maxlength
allowedvalues A scalar or unconstrained built-in type, or the items of a non-tuple array
pattern A definition with built-in type = "string"
keypattern A definition with built-in type = "collection"
min, max A numeric or temporal built-in type, or an array whose itemtype resolves to one comparable kind
minlength, maxlength A definition with built-in type = "string", type = "array", or type = "collection"
uniqueitems A definition with built-in type = "array"
dependentrequired, mutuallyexclusive, exactlyone A definition with effective type table or collection and fixed child definitions

A named type reference, alternative selector, and conditional selector may additionally declare only allof, description, optional, default, and deprecated. Kind-specific constraints for the referenced or alternative types belong in reusable definitions.

Quoted and Special Keys

Schema child definitions use TOML tables. When a target TOML key is empty or contains characters that TOML requires to be quoted, such as a literal dot, quote that key in the schema table path.

Target keys may have the same names as TOML Schema properties, such as type, itemtype, optional, or pattern. A key/value pair directly inside a schema definition is a schema property, while a table-header path segment below that definition is a target child definition.

A schema definition with nested child definitions and no explicit selector is treated as type = "table". This lets schemas describe target keys that would otherwise collide with schema properties.

TOML itself forbids one table from containing both a value and a subtable with the same key. Therefore, a definition cannot simultaneously use a schema property and define a target child with that property's name. For example, an implicit table can define [elements.plugin.type], but the parent cannot also declare a type = ... property. Likewise, a definition cannot have both a default = ... annotation and a child table named default. Authors can sometimes avoid a collision by factoring structure through a reusable type or by choosing the implicit-table form. If the colliding schema property is still required on the same definition, TOML Schema 1.0 cannot express both meanings there. Quoting the child key does not remove this TOML data model restriction.

Example TOML document:

"" = "blank"

[site]
"google.com" = true

[plugin]
type = "npm"

Schema:

[elements.""]
type = "string"

[elements.site."google.com"]
type = "boolean"

[elements.plugin.type]
type = "string"

Scalar and Unconstrained Built-in Types

The unconstrained built-in type is:

  • Any: any

The scalar built-in types are:

  • String: string
  • Integer: integer
  • Float: float
  • Boolean: boolean
  • Offset Date-Time: offset-date-time
  • Local Date-Time: local-date-time
  • Local Date: local-date
  • Local Time: local-time

Allowed Values - allowedvalues

allowedvalues provides an enumeration for a scalar or unconstrained built-in type. On an array, it instead enumerates the values permitted for each item, as described under Observations on Conditions to Arrays. It is invalid on a table or collection.

The allowedvalues array MUST contain at least one entry. Every entry on a non-array definition MUST have the TOML kind selected by that definition; type = "any" is the exception and permits entries of any TOML kind. Numeric equality between integers and floats does not make their TOML kinds interchangeable for this schema-load check. A malformed enumeration MUST be rejected at schema-load time.

For a non-array definition, when allowedvalues is combined with pattern, min, max, minlength, or maxlength, every entry in allowedvalues MUST satisfy every applicable constraint. A schema containing an entry that violates one of those constraints is malformed, and schema loaders MUST reject it at schema-load time. For offset date-times, this boundary check uses instant ordering even though subsequent allowedvalues membership uses parsed-value equality; equivalent instants with different retained local fields or offsets therefore compare equal for a boundary but remain distinct enumeration values.

After a schema with allowedvalues has been loaded successfully, a document value is valid when it is a member of allowedvalues according to Parsed Value Equality. Validators do not need to re-evaluate the other constraints for that document value because every enumerated value has already been checked against them while loading the schema.

The rules for applying allowedvalues to array items are defined separately under Observations on Conditions to Arrays.

Example:

[types.colorType]
type="string"
allowedvalues=[ "red", "black", "blue" ]

Minimum Value / Maximum Value - min and max

These properties define inclusive value ranges. They may only be used for:

  • float
  • integer
  • date and/or time types: offset-date-time, local-date-time, local-date, and local-time
  • array, when itemtype resolves to integer, float, or one of the temporal types above

For arrays, min and max apply to each item. itemtype MUST resolve to one comparable built-in kind: integer, float, offset-date-time, local-date-time, local-date, or local-time. All alternatives of a referenced oneof or anyof definition MUST resolve to that same kind. Schema loaders MUST reject array range constraints when the item schema can resolve to different kinds or to a non-comparable kind.

A min or max boundary MUST be a TOML value that is comparable with the schema type: integer or float boundaries for integer and float values, and matching temporal boundaries for temporal values.

nan, +nan, and -nan are not valid min or max boundaries because NaN is unordered. inf, +inf, and -inf are valid float boundaries.

Date/time boundaries compare only against values of the same TOML temporal type. For example, an offset-date-time boundary applies to offset-date-time values, not to local-date-time values.

Numeric ranges use mathematical ordering after TOML parsing. Integer-to-integer ordering MUST remain exact across the full signed 64-bit range. Mixed integer/float ordering MUST compare the exact integer with the parsed binary floating-point value without first rounding the integer to that floating-point format. Positive and negative zero have the same position. A document NaN is unordered and never satisfies a range constraint.

Offset date-times are ordered by the instant they identify after applying their offset; representations of the same instant compare equal even when their local fields and offsets differ. Local date-times, local dates, and local times are ordered lexicographically by their parsed fields, from the largest component to the smallest, including fractional seconds. No timezone or daylight-saving conversion is applied to a local temporal value.

Length - minlength and maxlength

These properties MUST be used only to define the allowed length of a string, an array, or a collection.

For string values, length is counted as the number of Unicode scalar values after TOML parsing and escape processing. It is not the number of UTF-8 bytes, UTF-16 code units, or user-perceived grapheme clusters. For example, "\U0001F600" has length 1, while "e\u0301" has length 2 because it is composed of two Unicode scalar values.

For an array, length is its number of items. For a collection, length is the number of dynamic entries to which itemtype applies; fixed child definitions are excluded from the count.

Both minlength and maxlength MUST be integers >= 0. When both are present, minlength MUST be less than or equal to maxlength. A schema violating either rule is malformed and schema loaders MUST reject it at schema-load time.

minlength and maxlength are valid only on definitions whose selected type is the built-in string, array, or collection. They cannot be attached to another built-in type, an alternative selector, or a named type reference. Schema loaders MUST reject an incompatible length constraint at schema-load time rather than silently ignoring it.

Container Types

  • Array: array
  • Table: table
  • Collection: collection

array and table correspond to parsed TOML value kinds. collection is a schema-level specialization of table for dynamically named entries. TOML inline tables parse as table values and therefore do not need a separate built-in type.

Tables

A table may have a set of properties, or none at all. If a table has a definition of properties, the validator MUST require the input to match exactly the rules of the table and its children.

If a schema definition has nested child definitions but does not declare a selector, schema loaders MUST treat it as if it declared type = "table".

If a property of type table has no defined children, the validator MUST accept any TOML table value without validating its contents. This is useful for representing custom data payloads.

Arrays

Arrays can be defined using the following properties:

  • itemtype: a type reference used to validate every item in a homogeneous array.
  • items: ordered type references for tuple-style positional validation with fixed arity.
  • minlength: the minimum length of the array (e.g. no less than 2 elements).
  • maxlength: the maximum length of the array (e.g. no more than 2 elements).
  • min: the minimum value allowed for each comparable array item (e.g. 80).
  • max: the maximum value allowed for each comparable array item (e.g. 8080).
  • allowedvalues: enumeration of possible values.
  • uniqueitems: whether every parsed array item must be unique.

Example for schema definition:

[elements.colors]
type="array"
itemtype="string"

Example of TOML file:

colors=[ "red", "yellow", "green" ]
Observations on Conditions to Arrays

The min and max conditions set an inclusive range for every array item. They MUST be used only when itemtype resolves to one comparable built-in kind: integer, float, or one of the four date/time types. When itemtype references a named definition, aliases and alternatives are resolved before this rule is checked.

Temporal values use the ordering rules defined under Minimum Value / Maximum Value.

When allowedvalues is present on an array, every array item MUST be a member of that enumeration. The enumeration does not have to be sorted. If min or max is also present, every enumerated value MUST satisfy the applicable inclusive boundary; an enumerated value need not equal either boundary.

When the array declares itemtype, every enumerated value MUST have a TOML kind permitted by the effective item type. Named references, aliases, and oneof or anyof alternatives are resolved before this check. An itemtype that permits any permits enumeration entries of any TOML kind. This schema-load check verifies the permitted TOML kind; constraints inside a named item definition still apply normally when a document array is validated.

minlength and maxlength constrain the document array's item count, not the number of entries in allowedvalues. The schema loader MUST reject an enumerated value that violates min or max.

If neither itemtype nor items is defined, array items default to any, so items of different TOML types may be mixed.

If type = "array" and itemtype = "array", every item MUST be an array. The contents of those nested arrays are unconstrained; only omitting itemtype permits non-array and array items to be mixed in the outer array.

Array Item Schemas and Arrays of Tables

itemtype accepts the same built-in or named references as type. Use a built-in reference such as itemtype = "string" for a homogeneous scalar array, or a reusable schema definition when members require constraints or structure. A reusable table definition is required for TOML arrays of tables and arrays of inline tables because both parse as arrays whose items are table values. The same keyword selects the type of each dynamic value in a collection.

Example with TOML arrays of tables:

[[products]]
name = "Hammer"
sku = 738594937

[[products]]
name = "Nail"
sku = 284758393

Schema:

[types.productType]
type = "table"

    [types.productType.name]
    type = "string"

    [types.productType.sku]
    type = "integer"

[elements.products]
type = "array"
itemtype = "types.productType"

Example with TOML arrays of inline tables:

points = [
  { x = 1, y = 2 },
  { x = 3, y = 4 }
]

Schema:

[types.pointType]
type = "table"

    [types.pointType.x]
    type = "integer"

    [types.pointType.y]
    type = "integer"

[elements.points]
type = "array"
itemtype = "types.pointType"
Tuple / Positional Array Validation - items

Use items to validate each array entry by position with an exact length.

Example:

[types.coordinate]
type = "float"

[types.label]
type = "string"

[types.coordinateLabel]
type = "array"
items = [ "types.coordinate", "types.label" ]

Semantics:

  • items is ordered, and each index validates against the corresponding referenced type.
  • items MUST contain at least one type reference. A schema loader MUST reject items = []; use maxlength = 0 to require an empty array.
  • When items is present, the array MUST have exactly the same number of items.
  • items is mutually exclusive with itemtype.
  • items is also mutually exclusive with min and max.
  • items is also mutually exclusive with minlength and maxlength.
  • items is mutually exclusive with allowedvalues; constraints for a tuple position belong in the reusable definition referenced at that position.
Array Uniqueness - uniqueitems

uniqueitems is a boolean property valid only on a definition whose selected type is the built-in array. When it is true, no two items in the document array may be equal. When it is false or absent, the schema imposes no uniqueness condition. It applies to homogeneous arrays, tuple arrays, and arrays whose item type is otherwise unconstrained.

Items are compared using Parsed Value Equality, recursively for arrays and tables.

Uniqueness compares complete item values. Version 1.0 does not define a field-selecting operation such as uniqueBy; two tables that share an id but differ elsewhere remain distinct. A schema loader MUST reject a non-boolean uniqueitems value or its use on a non-array definition.

Collection of Elements for Dynamic Keys

One can set an element of type collection when there is a need to have multiple children with dynamic, user-provided keys or table headers.

A collection is represented by a TOML table and may have fixed child definitions in addition to dynamically named entries. It remains a distinct schema type from table because it applies itemtype and collection unknown-key semantics to dynamic entries. Fixed children may use any schema definition, including nested tables, arrays, and named types.

A collection requires at least one effective itemtype constraint to define the type of its dynamic child values. The constraint may be declared locally or contributed by a compatible allof component. Each dynamic child must be given a unique key in the TOML document. itemtype may reference a built-in type or a named reusable definition. A schema loader MUST reject an effective collection when neither its local definition nor any referenced or composed definition contributes an itemtype.

The built-in collection cannot itself be used as itemtype or as an entry in items, oneof, anyof, or allof: those bare references provide no place to declare the nested collection's required itemtype. Define a reusable collection with its own itemtype and reference that named definition instead.

When collection values may have alternative types, define those alternatives in a reusable [types] definition with oneof or anyof, then reference that definition with itemtype. This keeps oneof and anyof consistently scoped to the current node rather than changing their meaning on a container.

A collection may additionally constrain the keys (entry names) of its dynamic children with keypattern. See Key Pattern - keypattern.

Fixed child definitions take precedence over the collection's dynamic-entry rule. This permits a collection to validate known keys precisely while applying itemtype only to all other keys. For example, itemtype = "any" makes unknown keys forward-compatible while fixed children still receive their declared validation. Authors choosing this pattern trade typo detection on unknown keys for extensibility; use a plain table when undeclared keys must be rejected.

This precedence also supports open extension namespaces with typed well-known entries. For example, a pyproject.toml schema can define [tool] as a collection of open tables, then add fixed [tool.ruff] and [tool.uv] child definitions with their respective schemas. Other tool names continue to use the collection's general itemtype.

Example: The below example shows a table servers that is a collection. Each server MUST be given a key and follow the defined structure of types.serverType. A server may also have a DNS table with user-provided key names.

TOML:

[servers]
group = "group1"

    [servers.alpha]
    name = "Alpha DC0"
    address = "dc0.alpha"

        [servers.alpha.dnstable]
        cloudflare = "1.1.1.1"
        google1 = "4.4.4.4"
        google2 = "8.8.8.8"
        internal = "mydns.intranet"

    [servers.beta]
    name = "Beta DC0"
    address = "dc0.beta"

TOML Schema:

[types]

    [types.dnsType]
    type = "string"
    pattern = "<ip-regex-pattern>"

    [types.hostnameType]
    type = "string"
    pattern = "<valid-hostname-regex-pattern>"

    [types.dnsValue]
    anyof = [ "types.dnsType", "types.hostnameType" ]

    [types.serverType]
    type = "table"

        [types.serverType.name]
        type = "string"

        [types.serverType.address]
        type = "string"

        [types.serverType.dnstable]
        type = "collection"
        itemtype = "types.dnsValue"
        optional = true

[elements]

    [elements.servers]
    type = "collection"
    itemtype = "types.serverType"

        [elements.servers.group]
        type = "string"

A collection may be represented as subtables of a common table in a TOML document.

Type Reference

A type reference applies a built-in type or inherits the rules of a named reusable type. Both [types] definitions and [elements] definitions may use type references. The type property selects the current node's type; built-in and named references use the same syntax.

When type selects a named reusable definition, the reference inherits that definition's validation rules as-is. This inheritance includes optional: the referencing slot is optional when either the use site or the referenced definition declares optional = true. A use-site optional = false cannot make an optional referenced definition required. In version 1.0, the referencing definition MAY additionally declare only allof, description, optional, default, and deprecated; it MUST NOT declare any other sibling property or child definition. allof adds conjunctive components rather than overriding the named reference. A local default is the use-site annotation described below, and deprecated = false cannot cancel deprecation inherited from a reference. In particular, validation constraints such as pattern, keypattern, min, max, minlength, maxlength, allowedvalues, itemtype, and items cannot be added or overridden at the reference site. Schema loaders MUST reject such schemas at schema-load time.

To specialize validation rules, declare another named reusable definition rather than adding constraints to a reference:

[types.lowercaseName]
type = "string"
pattern = "^[a-z]+$"

[elements.name]
type = "types.lowercaseName"
description = "Display name"
optional = true

The following is invalid because pattern attempts to override the referenced definition:

[types.name]
type = "string"
pattern = "^[a-z]+$"

[elements.name]
type = "types.name"
pattern = "^[A-Z]+$" # invalid
[types]

    [types.nameType]
    type="string"
    pattern="[a-zA-Z]"  # unanchored: matches any string containing a letter

    [types.serverType.name]
    type = "types.nameType"

    [types.serverType.enabled]
    type = "boolean"

[elements]

    [elements.datacenter]
    type="table"

        [elements.datacenter.name]
        type="types.nameType"

        [elements.datacenter.tags]
        type = "array"
        itemtype = "string"

        [elements.datacenter.servers]
        type = "collection"
        itemtype = "types.serverType"

Conjunctive Composition - allof

allof applies a non-empty array of type references to the current node in addition to its local definition. It is an applicator, not a type selector: the local definition must still declare one type, oneof, anyof, or conditional selector, or have fixed children that make it an implicit table.

[types.packageBase]
type = "table"

    [types.packageBase.version]
    type = "string"

[types.package]
type = "table"
allof = [ "types.packageBase" ]

    [types.package.name]
    type = "string"

The document value MUST validate against the local definition and every referenced component. Composition is conjunctive and non-overriding. If two components constrain the same value, both constraints apply. A contradiction may therefore describe a schema for which no document value is valid; it does not create last-wins behavior.

Every component MUST resolve to an effective TOML kind compatible with the local definition. When the local selector is oneof or anyof, all of its alternatives MUST resolve to the same effective kind before allof can be applied; a multi-kind local union combined with allof is indeterminate and MUST be rejected at schema-load time. Scalar and array components must have the same kind as the local definition. Structured components must all be table or all be collection; a table and a collection are not interchangeable for composition because they have different unknown-key semantics. A component whose alternatives resolve to different kinds is likewise indeterminate and MUST be rejected. The bare built-ins any and collection MUST NOT appear directly in allof; a complete named definition may resolve to either where it is otherwise compatible.

For composed arrays, the document array MUST independently satisfy the local array definition and every array component. Homogeneous itemtype constraints from different definitions all apply to every item. A tuple items constraint applies its exact length and per-position definitions independently of any homogeneous or tuple constraints contributed elsewhere. Array length, uniqueness, enumeration, and item range constraints likewise remain conjunctive. Conflicting constraints may make the definition unsatisfiable but do not use last-wins merging and are not by themselves a schema-load error.

For composed tables and collections, validators MUST form the union of all local and component fixed-child names before applying unknown-key rules. The value of an overlapping fixed child MUST validate against every contributing child definition. If any contributing child definition requires that child, the child remains required.

A composed table is open only when neither the local definition nor any component defines fixed children. Otherwise its union of fixed children is closed. For a composed collection, the union of fixed children retains precedence over dynamic entries. Every remaining dynamic entry MUST satisfy every contributing itemtype, and its key MUST satisfy every contributing keypattern. A collection's required dynamic-entry constraint may therefore be supplied entirely by one or more allof components; it need not repeat a local itemtype.

optional on the local definition determines whether the composed node may be absent. An optional value inside an allof component does not make the composed node optional; it only has meaning when that component is referenced normally with type.

An allof component may itself contain oneof, anyof, or another allof when its effective kind is unambiguous. A composed definition may be referenced from type, itemtype, items, oneof, anyof, then, or else. All composition references MUST resolve at schema-load time, and composition/type-selection cycles are malformed. Structural recursion that consumes a child or container member remains valid.

Alternative Types - oneof and anyof

Use oneof or anyof when a value may validate against alternative type references.

  • oneof: exactly one referenced type must validate.
  • anyof: at least one referenced type must validate.

These properties can be used anywhere a schema definition can appear, including an [elements] field, a reusable [types] definition, and a type referenced through itemtype for array or collection items. Alternatives may reference built-in type names directly or named definitions when a branch needs constraints.

The bare built-in names any and collection MUST NOT appear directly in oneof or anyof. Use a named reusable definition when an alternative needs a fully defined collection or an intentionally unconstrained named branch.

type, oneof, anyof, and the conditional triple all select the current node's type and are mutually exclusive. A schema loader MUST reject a definition containing more than one selector.

The array assigned to oneof or anyof MUST contain at least one type reference. A union definition MAY additionally declare only description, optional, default, deprecated, and allof; it MUST NOT declare another validation property or any nested child definition. Schema loaders MUST reject empty unions and other union siblings at schema-load time. Constraints required by an alternative belong in a named reusable definition referenced by the union.

[types.stringId]
type = "string"
pattern = "^[a-z]+$"

[types.integerId]
type = "integer"
min = 1

[elements.id]
anyof = [ "types.stringId", "types.integerId" ]

[elements.simpleId]
oneof = [ "string", "integer" ]

Use a named reusable definition whenever an alternative needs constraints such as pattern, min, allowedvalues, itemtype, or child fields.

[types.dependencyVersion]
type = "string"
pattern = "^[0-9]+\\.[0-9]+\\.[0-9]+$"

[types.inlineDependency]
type = "table"

[types.dependency]
oneof = [ "types.dependencyVersion", "types.inlineDependency" ]

For container items with alternative types, use a named wrapper:

[types.dnsValue]
oneof = [ "types.ipAddress", "types.hostname" ]

[elements.dns]
type = "collection"
itemtype = "types.dnsValue"

A named container definition can also be an alternative. This models formats that accept either one table or an array of the same table shape:

[types.cascadeEntry]
type = "table"

    [types.cascadeEntry.params]
    type = "table"
    optional = true

[types.cascadeEntries]
type = "array"
itemtype = "types.cascadeEntry"

[elements.cascade]
oneof = [ "types.cascadeEntry", "types.cascadeEntries" ]

When alternatives contain annotations, only successful branches contribute them, and only for a value that is present. Deprecation warnings follow the successful-branch rule: oneof reports the warning of its single successful branch, and anyof reports the warnings of every successful branch, deduplicated by code, path, and message. Consequently, a deprecated successful branch contributes a warning even when another successful anyof branch is not deprecated; this preserves all annotations attached to definitions that accepted the value. Alternative default annotations are governed by Default: they are never combined into the slot's effective default and never cause a schema-load conflict. For a present value, an implementation MAY surface the default of each successful branch as a hint, deduplicated by Parsed Value Equality. A branch that fails validation contributes neither defaults nor deprecation warnings.

Conditional Selection - if, then, and else

The if, then, and else properties form one exhaustive selector for a table-like node. The condition inspects one direct child of the current parsed table and selects one of two named reusable definitions:

[types.database]
if = { key = "engine", equals = "sqlite" }
then = "types.sqliteDatabase"
else = "types.serverDatabase"

if MUST be an inline table containing key and exactly one of equals or in. It MUST contain no other members.

  • key MUST be a string naming one direct child of the current node. It is a decoded TOML key, not a dotted document path. An empty or literal dotted key is permitted.
  • equals accepts one TOML value. The condition succeeds when the child exists and is equal to that value according to Parsed Value Equality.
  • in MUST be a non-empty array. The condition succeeds when the child exists and is equal to at least one array entry according to Parsed Value Equality.

If the named child is absent, the condition is false. A validator MUST apply only the selected branch: then when the condition is true and else when it is false. The condition itself emits no document-validation diagnostic. Validation diagnostics and deprecation annotations come only from the selected branch. A branch default does not become the conditional slot's effective default; for a present value, an implementation MAY surface the selected branch's default as a hint.

then and else MUST each be a string naming a reusable definition in [types]; bare built-in references are invalid. Both definitions MUST resolve to the same effective kind, and that kind MUST be table or collection. Schema loaders MUST reject unresolved branches, different branch kinds, branches that do not resolve to a table-like kind, and cycles through conditional branches.

The conditional triple is mutually exclusive with type, oneof, and anyof. A conditional definition MAY additionally declare only allof, description, optional, default, and deprecated; it MUST NOT contain kind-specific validation properties or nested child definitions. An allof component MUST be compatible with the common branch kind and is applied conjunctively with whichever branch is selected.

Optionality belongs to the conditional definition. An optional annotation inside a branch does not make the conditional slot optional, because no branch is selected when the slot is absent. A default on the conditional definition MUST validate against the branch selected by that default at schema-load time.

Example with a multi-value condition:

[types.database]
if = { key = "engine", in = [ "postgresql", "mysql" ] }
then = "types.serverDatabase"
else = "types.embeddedDatabase"

Additional alternatives can be expressed by referencing another conditional definition from then or else.

Sibling Presence Rules

Version 1.0 defines three presence-only rules for direct fixed children of an effective table or collection. They inspect parsed key presence, never a child's value, and never follow a dotted string as a document path.

Dependencies - dependentrequired

dependentrequired is a non-empty inline table. Each member maps one trigger child name to a non-empty array of unique child names. When the trigger is present, every listed child MUST also be present.

Because dependentrequired is also a legal child key, a dependentrequired = { ... } key/value entry is always the sibling rule, while a table header such as [types.example.dependentrequired] is always a child definition named dependentrequired.

[types.dependency]
type = "table"
dependentrequired = { branch = [ "git" ], tag = [ "git" ], rev = [ "git" ] }

Dependencies are directional. If a requires b, the presence of b does not require a unless a reverse mapping is declared. Every triggered mapping is evaluated, so dependencies may apply transitively.

Mutual Exclusion - mutuallyexclusive

mutuallyexclusive is a non-empty array of groups. Each group is an array of at least two unique child-name strings. At most one member of each group may be present.

mutuallyexclusive = [ [ "git", "path" ], [ "branch", "tag", "rev" ] ]

Zero or one present member satisfies a group.

Exactly One - exactlyone

exactlyone has the same shape as mutuallyexclusive, but exactly one member of every group MUST be present.

[types.readmeTable]
type = "table"
exactlyone = [ [ "file", "text" ] ]

This allows every group member to remain individually optional = true while the group still requires one choice.

Every name in these three properties MUST identify a direct fixed child in the effective definition after allof composition. A quoted string containing a dot identifies a literal dotted child key. Dynamic collection keys are not fixed children and cannot be operands, while a collection's explicitly defined children participate normally.

Schema loaders MUST reject a rule with the wrong TOML value type, an empty mapping or group list, a group with fewer than two members, a duplicate name within one dependency array or group, an unknown fixed-child name, or use on an incompatible effective kind. Loaders are not required to prove general logical satisfiability between multiple valid rules.

Ordinary requiredness is evaluated together with these rules. An absent optional trigger has no effect. A non-optional child remains required even if a presence group would otherwise permit its absence.

Description - description

description is an optional human-readable string that documents a schema definition. It may be used on reusable types, elements, and nested definitions. Implementations and tooling MAY use it for documentation, suggestions, and autocompletion; it does not affect validation.

[types.game]
type = "table"
description = "A game object."

    [types.game.id]
    type = "string"
    description = "Unique identifier for the game."

[elements.game]
type = "array"
description = "A list of games."
itemtype = "types.game"

Default - default

default is a machine-readable annotation containing any TOML value.

[elements.retries]
type = "integer"
optional = true
default = 3

Because default is also a legal child key, a default = <value> key/value entry is always the annotation, while a table header such as [elements.options.default] is always a child definition named default. Consequently, a table-valued default MUST use inline-table syntax, for example default = { min = 1, max = 10 }.

A default is not a validation assertion and never changes the document being validated. It does not insert a missing value, satisfy a required definition, or change the parsed TOML data returned by an implementation. Tools MAY expose it as a suggestion or effective-configuration hint through schema metadata. Version 1.0 does not define an operation that materializes defaults.

Despite being an annotation, a declared default MUST validate as a present value against the full effective definition at schema-load time. Default validation applies all references, composition, alternatives, fixed children, sibling rules, and ordinary constraints, but does not emit a deprecation warning. A loader MUST reject an incompatible default.

A default declared directly at a use site takes precedence over one inherited through its type reference. Without a use-site default, the referenced default is inherited. Defaults contributed by allof components are compared using Parsed Value Equality. Equal defaults are deduplicated. If components contribute unequal defaults and the local definition has no default, the schema is malformed because it has no single effective default. A valid local default resolves that annotation conflict and must still satisfy every component.

Alternative selectors do not contribute to a slot's effective default. The effective default of a slot whose selector resolves to oneof or anyof is determined only by a use-site default, a default inherited through the named type reference chain that resolves to the union, and defaults composed through allof, using the precedence and conflict rules above. A default declared on an individual alternative is never aggregated into the union's effective default and never causes a schema-load conflict, even when several anyof alternatives declare unequal defaults. A loader MUST NOT reject a schema solely because two alternatives declare defaults, equal or unequal. Resolving effective defaults therefore never requires deciding whether two alternatives can match the same value.

When a union slot is absent, only this effective default applies; if none exists, the slot has no default. When the slot value is present, default does not change it, so alternative defaults surfaced under the successful-branch rule are informational hints. An implementation MAY expose the default of each successful alternative, deduplicated by Parsed Value Equality, but MUST NOT treat multiple present-value alternative defaults as an error.

Deprecation - deprecated

deprecated is a boolean annotation. When true, it advises that the present value at that schema location should no longer be used and may be removed in a future version.

[elements.legacy-timeout]
type = "integer"
deprecated = true
description = "Use request-timeout instead."
optional = true

Deprecation never makes a document invalid. A successfully validated present value produces a warning diagnostic; an absent optional value produces no warning. A deprecated parent produces one warning at the parent path rather than one warning for every descendant.

Deprecation propagates through named references. Across allof, any contributing deprecated = true deprecates the location, and a local deprecated = false cannot cancel it. Alternative branches follow the successful-branch annotation rules defined above. A non-boolean deprecated value is a schema-load error. Authors SHOULD use description for migration or replacement guidance.

Optionality - optional

Properties may be defined as optional in the schema. By default, optional equals false, and the structure is required.

Validators MUST skip a definition only when it is optional and the corresponding value does not exist in the TOML document. In every other case, the validator MUST validate the value against the definition.

For a named type reference, optionality is inherited: the referencing slot is optional if either the use site or any definition in the reference chain declares optional = true. An explicit optional = false cannot cancel an inherited true. In contrast, optional values contributed only through allof components do not affect presence, as defined under Conjunctive Composition. The presence of a oneof or anyof slot is governed only by optional on the union definition or inherited through a named type reference to that union. optional declared inside an alternative does not make the union slot optional because no alternative is selected when the slot is absent.

Pattern - pattern

This property is only valid on a definition whose selected type is the built-in string. It cannot be attached to another built-in type, an alternative selector, or a named type reference. Schema loaders MUST reject an incompatible pattern at schema-load time rather than silently ignoring it.

The portable TOML Schema regular-expression profile consists of literals, escaped metacharacters, ., character classes and ranges, negated character classes, concatenation, alternation, capturing and non-capturing groups, the anchors ^ and $, and the greedy quantifiers ?, *, +, {n}, {n,}, and {n,m}. These constructs use the syntax documented by the RE2 syntax reference. Implementations MUST support this profile.

Character-class shorthands such as \d, \s, and \w are outside the portable profile because regular-expression engines disagree about whether they use ASCII or Unicode membership. Backreferences, look-around assertions, atomic groups, conditionals, and recursion are also outside the portable profile. Implementations MAY accept additional constructs, but schemas that use those extensions are not portable between TOML Schema implementations.

The pattern is not implicitly anchored. A value validates if the regular expression matches anywhere in the string. Authors who require a full-string match MUST anchor the expression with ^ and $.

Patterns are evaluated without multiline or dot-all modes. ^ matches only the start of the complete parsed string, $ matches only its end (not a position before a final line feed), and . does not match a line feed. These rules also apply when an implementation uses a regular-expression engine with different defaults.

Key Pattern - keypattern

This property may only be used on a collection. It constrains the keys (entry names) of the collection's dynamic children: every dynamically keyed entry must match the provided regular expression. It does not validate entry values — that is the role of itemtype. It is therefore orthogonal to itemtype and may be combined with it.

keypattern is invalid on any non-collection type (scalars, array, plain table), and a schema loader MUST reject a schema that uses it elsewhere.

Keys that are explicitly declared as fixed child definitions of the collection (schema-restricted key-value pairs) are validated by their own definitions and are not subject to keypattern. Only dynamic, user-provided keys are matched against the pattern.

Implementations MUST support the same portable RE2 regular-expression profile as pattern. Like pattern, keypattern is not implicitly anchored: a key validates if the regular expression matches anywhere in the key string. Authors who require a full-key match MUST anchor the expression with ^ and $.

Example:

[types.listOfServersType]
type       = "collection"
itemtype   = "types.serverType"
minlength  = 1
keypattern = "^server_[0-9]+$"

Against a TOML document:

[servers.server_01]   # accepted
[servers.server_02]   # accepted
[servers.alpha]       # rejected: key does not match ^server_[0-9]+$

This mirrors JSON Schema's propertyNames: { pattern: ... }, applied to TOML maps.

Validation and Data Model

TOML Schema validation does not modify the parsed TOML data model.

A validator MUST NOT mutate, replace, or augment the TOML data object produced by the underlying parser. An API that returns that object MUST return the same parsed keys and values that would exist without schema validation.

Schema loading additionally requires source-shape information for inline-table properties whose names may also name child definitions. In particular, default = { ... } and dependentrequired = { ... } cannot be distinguished from same-named child tables by their logical TOML values alone. A schema loader MUST use a parser that preserves key/value-versus-table syntax or exposes enough source-position information to recover it; a logical-value-only TOML API is insufficient for this distinction. Loaders MUST NOT guess from inline-table member names.

Parsed Value Equality

TOML Schema uses one equality relation for allowedvalues membership, uniqueitems, and comparison of defaults contributed by composition. Equality is defined over parsed TOML values:

  • strings and booleans compare by value, without Unicode normalization;
  • numeric values compare by mathematical value, so integer 1 equals float 1.0, positive and negative zero are equal, and NaN equals NaN only for this equality relation;
  • integer comparison remains exact across the full TOML signed 64-bit range, including comparison with a float, and implementations MUST NOT first round the integer to the float's binary format;
  • temporal values require the same TOML temporal type and the same parsed fields, including the numeric UTC offset for an offset date-time; equivalent spellings such as .1 and .100 or Z and +00:00 are equal, but offset date-times with different retained local fields or offsets are unequal even when they identify the same instant;
  • arrays compare by length and equal values at every index; and
  • tables compare by their unordered parsed key sets and recursively equal values. Source key order, table syntax, and lexical spelling do not participate.

This equality relation is distinct from the ordering used by min and max. In particular, offset date-times that identify the same instant compare equal for a range boundary but remain unequal here when their retained local fields or offsets differ. Implementations MUST NOT reuse instant ordering as allowedvalues, uniqueitems, or default-comparison equality.

Validation Diagnostics

Implementations MUST distinguish schema-load failures from document-validation diagnostics. A malformed schema, unsupported language version, unresolved reference, or invalid keyword application prevents validation from starting.

Document-validation diagnostics have a severity, stable machine-readable code, document path, and human-readable message. Errors determine document validity. Warnings do not. Except for the deprecated code assigned below and any codes assigned by a future revision of this specification, diagnostic codes and path serialization are implementation-defined, but they MUST remain stable across compatible releases of that implementation. An implementation MAY expose additional diagnostic fields, but MUST provide separate access to errors and warnings. A command-line validator MUST exit successfully for a document whose only diagnostics are warnings.

Deprecation produces a warning with the stable machine-readable code deprecated. Implementations MUST retain branch-local diagnostics while evaluating oneof and anyof so warnings from failed alternatives are not reported. Duplicate warnings contributed by multiple successful paths MUST be deduplicated by code, path, and message.

Expressiveness and Validation Scope

TOML Schema describes the parsed TOML value tree. It can model the structural patterns used by major configuration formats, including:

  • fixed keys and closed tables;
  • open tables for extension-owned data;
  • dynamic-key maps with uniform values by using collection;
  • open namespaces with specially typed well-known keys by combining a collection with fixed child definitions;
  • arrays of tables and arrays of inline tables by using a named table as an array's itemtype;
  • scalar-or-table and other alternative representations with oneof or anyof;
  • table shapes selected from a direct child's value with if, then, and else;
  • single-table-or-array-of-table representations through named container alternatives;
  • fixed-length heterogeneous arrays with items; and
  • quoted, empty, or literal dotted keys through normal TOML key syntax.

The checked-in schemas under examples/ exercise these patterns against formats including Cargo manifests, Python pyproject.toml, Hugo, Netlify, GitLab Runner, and Cloudflare Wrangler.

Version 1.0 includes direct-sibling value conditionals, direct-sibling presence dependencies, at-most-one and exactly-one groups, conjunctive reusable composition, whole-item array uniqueness, defaults, and deprecation annotations. These features remain deliberately bounded. Version 1.0 does not define keywords for:

  • following arbitrary document paths or comparing values at different paths;
  • making a field absent precisely when its name appears in another array;
  • selecting array uniqueness by one field rather than the complete item value;
  • materializing defaults into parsed TOML data; or
  • overriding a constraint or modeling an application's runtime inheritance and merge precedence.

For example, a schema can choose a database configuration shape from a sibling engine value. It still cannot compare values in different tables or follow an arbitrary path from one location to another. A pyproject.toml schema can require project.dynamic entries to be unique, but cannot require a field to be absent precisely when its name appears in that array. Those cross-path application policies require an additional semantic-validation pass.

Some configuration sections intentionally combine known fields with arbitrary future or extension-owned fields. A collection with fixed child definitions and itemtype = "any" models that forward-compatible shape, but unknown keys cannot then be distinguished from misspellings. Schema authors SHOULD prefer a closed table when the upstream format defines a stable, exhaustive key set.

Version 1.0 defines default and deprecated; examples and editor-specific presentation hints remain outside the standard vocabulary.

Validation applies to parsed keys and values, not to their lexical spelling. A schema cannot require dotted-key notation instead of table headers, an inline table instead of a regular table, or a particular quoting, whitespace, or comment style when those forms produce the same TOML value tree.

Filename Extension

TOML Schema files MUST use the extension .tosd.

MIME Type

TOML Schema documents are valid TOML documents. When transferring them over the internet, implementations SHOULD use the registered TOML media type:

  • application/toml

TOML Reference of a TOML Schema

A TOML file can include this indication to reference which schema file to use for validation:

[toml-schema]
location = "<uri>"
version = "1.0.0" # optional

location identifies the schema document. It is REQUIRED when a validator is asked to discover a schema from the TOML document. Its value MUST be a non-empty string containing either an absolute URI, such as an HTTPS URL, or a relative URI reference, such as a local schema filename.

An absolute location MUST be used unchanged. A relative location MUST be resolved against the referencing TOML document's location, not against the validator's current working directory or the resolved schema's location. For a TOML document stored in a local file, this means resolving a relative location from the document's parent directory.

A validator that receives a TOML document without a base location, for example through standard input, cannot resolve a relative location. It MUST either obtain an explicit base URI from the caller or report that schema discovery failed. An absolute location does not require a document base. Implementations MAY limit the URI schemes they can retrieve, but MUST report an unsupported scheme rather than reinterpret its value as a relative local path.

An implementation that supports the file scheme MUST require a hierarchical file URI that can be converted to a local path, such as file:///schemas/config.tosd. It MUST reject an opaque URI such as file:schema.tosd rather than reinterpret it as a path relative to the TOML document. A file URI with a query or fragment MUST also be rejected because those components are not part of the local filesystem path.

version is OPTIONAL. When present, it denotes the expected TOML Schema language version in the resolved schema document's [toml-schema].version; it is not an application version or an author-defined revision of that schema. Its value MUST be a string containing a complete Semantic Versioning 2.0.0 value: the MAJOR.MINOR.PATCH core is required, and valid pre-release and build suffixes are optional, as defined by Schema Versioning.

After resolving and loading the schema, a validator MUST compare these two language versions when the referencing document provides version. A different major version is incompatible and schema discovery MUST fail. Any other unequal version, including a minor, patch, pre-release, or build metadata difference, MUST produce a warning but MUST NOT by itself cause validation to fail. Compatibility between the resolved schema and the validator remains governed by Schema Versioning.

In a target TOML document, the root [toml-schema] table is reserved for schema-reference metadata. This is a different context from the metadata table inside a schema document, which may contain [toml-schema.meta] as described under Metadata Table - [toml-schema]. location and version are the only keys interpreted by this specification. Implementations MAY permit additional extension keys, but every direct value in this table MUST be a TOML scalar: string, integer, float, boolean, offset date-time, local date-time, local date, or local time. Arrays, inline tables, subtables, and arrays of tables are not schema-reference metadata and MUST be rejected during schema discovery. Implementations MUST ignore extension keys they do not recognize.

When [elements.toml-schema] is omitted, validators MUST ignore the reserved metadata table during application-data validation. When [elements.toml-schema] is present, validators MUST additionally validate the metadata table like any other application table. Schema discovery rules, including the scalar-only restriction, still apply when discovery is requested.