Basker Docs

Validation errors

Catalogue of validation errors and warnings raised during theme upload

This reference documents every validation error and warning that the theme validator can produce. Entries are organised by severity: errors first (must be fixed before a theme can be published), then warnings (advisory, non-blocking). Each entry includes the error code, the message shown, the cause, and the fix.

The validator runs in two contexts:

  • Upload validation -- runs server-side when a theme ZIP is uploaded via the CMS.
  • Local validation -- runs via localstage theme check during development.

Both validators share the same rule set. The error codes listed below apply to both contexts.

Overview

CodeSeverityCategory
missing-layoutsErrorManifest
missing-default-layoutErrorManifest
block-missing-schemaErrorSchema
block-duplicate-nameWarningSchema
invalid-schema-jsonErrorSchema
unsupported-field-typeWarningSchema
unsupported-asset-typeErrorAsset Integrity
missing-asset-referenceErrorAsset Integrity
invalid-layout-referenceErrorManifest
missing-schema-tagWarningSchema
multiple-schema-tagsWarningSchema
orphaned-assetsWarningAsset Integrity
large-assetWarningBest Practice
deprecated-includeWarningCompatibility
missing-meta-descriptionWarningBest Practice
deep-nestingWarningBest Practice

Errors

missing-layouts

Severity: Error Category: Manifest Completeness Message: Missing required directory: layouts.

Cause: The theme ZIP does not contain a layouts/ directory. Every theme must include at least one layout file.

Fix: Create a layouts/ directory in the root of the theme and add at least default.liquid.

Example:

Before (incorrect directory structure):

my-theme/
  templates/
    page.liquid
  blocks/
    hero.liquid

After (correct directory structure):

my-theme/
  layouts/
    default.liquid
  templates/
    page.liquid
  blocks/
    hero.liquid

See also:

missing-default-layout

Severity: Error Category: Manifest Completeness Message: Missing layouts/default.liquid.

Cause: The layouts/ directory exists but does not contain default.liquid. This file is the fallback layout used when a template does not specify a layout via {% layout %}.

Fix: Create layouts/default.liquid with a {{ content_for_layout }} output tag.

Example:

<!DOCTYPE html>
<html>
<head>
  <title>{{ page.title }}</title>
  {{ "styles.css" | asset_url | stylesheet_tag }}
</head>
<body>
  {{ content_for_layout }}
</body>
</html>

See also:

block-missing-schema

Severity: Error Category: Schema Validation Message: Block is missing a schema tag. / Block schema is missing.

Cause: A .liquid file in blocks/ does not contain a {% schema %}...{% endschema %} tag. Every block file must declare its schema so the CMS can generate the corresponding editor fields.

Fix: Add a {% schema %} tag containing valid JSON with at minimum name and settings properties.

Example:

Before:

<section class="hero">
  <h1>{{ block.heading }}</h1>
</section>

After:

<section class="hero">
  <h1>{{ block.heading }}</h1>
</section>

{% schema %}
{
  "name": "hero",
  "label": "Hero",
  "singular": "Hero",
  "plural": "Heroes",
  "settings": [
    {
      "name": "heading",
      "type": "text",
      "label": "Heading"
    }
  ]
}
{% endschema %}

See also:

block-duplicate-name

Severity: Warning Category: Schema Validation Message: Duplicate block name '<name>' (also in <file>).

Cause: Two or more block files declare the same name value in their {% schema %} tag. Block names are used as unique identifiers when templates reference blocks via allowed_blocks.

Fix: Ensure every block has a unique name value in its schema. Rename one of the conflicting blocks.

Example:

Before (blocks/hero.liquid and blocks/hero-alt.liquid both use "name": "hero"):

{
  "name": "hero",
  "settings": []
}

After (rename the second block):

{
  "name": "hero-alternate",
  "settings": []
}

invalid-schema-json

Severity: Error Category: Schema Validation Message: Invalid block schema JSON: <parse error> / Invalid template schema JSON: <parse error> / Schema tag is empty.

Cause: The content between {% schema %} and {% endschema %} is not valid JSON. Common causes include trailing commas, unquoted keys, missing closing brackets, or an entirely empty schema tag.

Fix: Validate the JSON syntax. Use a JSON linter or paste the schema content into a validator. Ensure all keys are double-quoted, brackets are balanced, and there are no trailing commas.

Example:

Before (trailing comma):

{% schema %}
{
  "name": "hero",
  "settings": [
    { "name": "heading", "type": "text" },
  ]
}
{% endschema %}

After (trailing comma removed):

{% schema %}
{
  "name": "hero",
  "settings": [
    { "name": "heading", "type": "text" }
  ]
}
{% endschema %}

See also:

unsupported-field-type

Severity: Warning Category: Schema Validation Message: Unsupported field type "<type>".

Cause: A field in the schema settings array uses a type value that is not in the allowed list. The validator will report this but will not block the upload.

Fix: Use one of the 20 allowed field types:

TypeDescription
textSingle-line text input
textAreaMulti-line text input
emailEmail address input
urlURL input
numberNumeric input
checkboxBoolean checkbox
switchBoolean toggle switch
colorColour picker
dateDate picker
dateTimeDate and time picker
radioRadio button group
selectDropdown select
codeCode editor
jsonJSON editor
richTextRich text editor (the rich text editor)
hiddenHidden field
relationshipRelationship to another document
uploadFile upload
arrayRepeatable group of fields
groupStatic group of nested fields

The validator also accepts common case variations and normalises them automatically: richtext becomes richText, textarea becomes textArea, datetime becomes dateTime.

Example:

Before:

{ "name": "colour", "type": "colorPicker" }

After:

{ "name": "colour", "type": "color" }

unsupported-asset-type

Severity: Error Category: Asset Integrity Message: Asset type .<extension> is not allowed.

Cause: A file in the assets/ directory uses a file extension that is not on the allowed list.

Fix: Only use files with the following extensions in assets/:

css, eot, gif, ico, jpg, jpeg, js, json, png, svg, ttf, webp, woff, woff2

Convert or remove files with disallowed extensions. For example, convert .bmp images to .png or .webp.

Example:

Before:

assets/
  background.bmp
  logo.tiff

After:

assets/
  background.webp
  logo.png

missing-asset-reference

Severity: Error Category: Asset Integrity Message: Missing asset assets/<path>.

Cause: A template references an asset file via the asset_url filter or a direct path, but the referenced file does not exist in the assets/ directory.

Fix: Either add the missing file to assets/ or correct the path in the template.

Example:

Before (template references a file that does not exist):

{{ "styles/main.css" | asset_url | stylesheet_tag }}
assets/
  style.css       <-- filename does not match

After (correct the filename or the reference):

{{ "style.css" | asset_url | stylesheet_tag }}

invalid-layout-reference

Severity: Error Category: Manifest Completeness Message: Layout reference "<name>" does not exist.

Cause: A template uses {% layout '<name>' %} but the referenced layout file does not exist in the layouts/ directory.

Fix: Either create the missing layout file or update the {% layout %} tag to reference an existing layout. If the template should use the default layout, remove the {% layout %} tag entirely or use {% layout 'default' %}.

Example:

Before (template references non-existent layout):

{% layout 'fullwidth' %}
<h1>{{ page.title }}</h1>

Fix option 1 -- create the layout:

layouts/
  default.liquid
  fullwidth.liquid   <-- add this file

Fix option 2 -- update the reference:

{% layout 'default' %}
<h1>{{ page.title }}</h1>

Warnings

missing-schema-tag

Severity: Warning Category: Schema Validation Message: Template is missing a schema tag. / Block is missing a schema tag.

Cause: A .liquid file in templates/ or blocks/ does not contain a {% schema %} tag. While not strictly required for templates, a schema allows the CMS to generate editable fields and configure block allowlists.

Fix: Add a {% schema %} tag. Even if the template has no configurable settings, include an empty settings array.

Example:

{% schema %}
{
  "settings": [],
  "blocks": ["hero", "text-section"]
}
{% endschema %}

See also:

multiple-schema-tags

Severity: Warning Category: Schema Validation Message: Block has multiple schema tags; only the first will be used. / Template has multiple schema tags; only the first will be used.

Cause: A .liquid file contains more than one {% schema %}...{% endschema %} block. The validator only parses the first one and ignores subsequent schema tags.

Fix: Remove all but one {% schema %} tag from the file. Consolidate settings into a single schema block.

Example:

Before:

{% schema %}
{ "name": "hero", "settings": [{ "name": "heading", "type": "text" }] }
{% endschema %}

{% schema %}
{ "name": "hero", "settings": [{ "name": "subheading", "type": "text" }] }
{% endschema %}

After:

{% schema %}
{
  "name": "hero",
  "settings": [
    { "name": "heading", "type": "text" },
    { "name": "subheading", "type": "text" }
  ]
}
{% endschema %}

orphaned-assets

Severity: Warning Category: Asset Integrity Message: Orphaned asset assets/<path>.

Cause: A file exists in the assets/ directory but is not referenced by any template, layout, or snippet via asset_url or a direct path. This increases the theme bundle size without benefit.

Fix: Remove unused asset files from the assets/ directory. If the asset is used dynamically (e.g. via a setting value), you can safely ignore this warning.

large-asset

Severity: Warning Category: Best Practice / Asset Integrity Message: Image exceeds recommended size (<size> bytes). / Asset exceeds recommended size (<size> bytes).

Cause: An asset file exceeds the recommended size limits:

  • Images (gif, ico, jpg, jpeg, png, svg, webp): 1.5 MB
  • Other assets (css, js, fonts, etc.): 2.5 MB

Fix: Optimise the file:

  • Compress images using tools such as sharp, imagemin, or an online compressor.
  • Convert images to modern formats like .webp.
  • Minify CSS and JavaScript files.
  • Subset web fonts to include only the required character ranges.

deprecated-include

Severity: Warning Category: Compatibility Message: Include tags are deprecated. Use render instead.

Cause: A template uses the {% include %} tag. This tag is deprecated in favour of {% render %}, which provides better encapsulation and does not leak variables into the parent scope.

Fix: Replace {% include %} with {% render %}. Note that {% render %} has different variable scoping -- pass variables explicitly.

Example:

Before:

{% include 'header' %}

After:

{% render 'header', site: site, page: page %}

missing-meta-description

Severity: Warning Category: Best Practice Message: No meta description tag found in templates or layouts.

Cause: No template or layout in the theme includes a <meta name="description"> tag. Search engines use this tag for indexing and display in search results.

Fix: Add a meta description tag to the layout or to individual templates.

Example:

<head>
  <meta name="description" content="{{ page.meta_description | default: site.description }}">
</head>

deep-nesting

Severity: Warning Category: Best Practice Message: Field nesting depth is <depth>. Consider simplifying complex groups or arrays.

Cause: A schema's field structure (using group or array types) exceeds 4 levels of nesting. Deeply nested schemas produce complex editor interfaces and can degrade the content editing experience.

Fix: Simplify the schema structure. Flatten nested groups where possible, or split deeply nested configurations into separate blocks.

Example:

Before (5 levels deep):

{
  "name": "layout",
  "type": "group",
  "fields": [
    {
      "name": "section",
      "type": "group",
      "fields": [
        {
          "name": "column",
          "type": "group",
          "fields": [
            {
              "name": "items",
              "type": "array",
              "fields": [
                { "name": "label", "type": "text" }
              ]
            }
          ]
        }
      ]
    }
  ]
}

After (3 levels, flattened):

{
  "name": "items",
  "type": "array",
  "fields": [
    { "name": "section_label", "type": "text" },
    { "name": "column_label", "type": "text" },
    { "name": "item_label", "type": "text" }
  ]
}

Index

By severity

Errors

Warnings

By category

Schema Validation

Asset Integrity

Manifest Completeness

Compatibility

Best Practice

On this page