stories validate
Checks the content of every story in a Storyblok space against a local TypeScript schema. The command is read-only: it modifies nothing in the space.
Use it to find content that no longer fits the schema: a block removed from the code, a field renamed, a required field never filled in, or an option value that no longer exists.
Option values are only checked for fields whose options are defined in the schema itself (self-sourced). A field with a source (an internal datasource, internal_stories, internal_languages, or external) resolves its options inside the space, and a datasource definition carries no entries, because entries are content rather than schema. Those values are therefore not knowable from local code.
Prerequisites
Section titled “Prerequisites”- An entry file that exports at least one block, authored with
@storyblok/schema. Story content cannot be validated against a schema that defines no blocks, so such an entry file is rejected with exit code2instead of reportingunknown_componenton every story.
storyblok stories validate [flags]| Flag | Type | Description |
|---|---|---|
--space, -s |
integer | Required. The ID of the Storyblok space whose stories are validated. |
--schema |
string | Required. Path to the TypeScript schema entry file. |
--starts-with |
string | Optional. Only validate stories whose path starts with this prefix, for example en/blog/. |
--level |
string | Optional. Display threshold: error hides warnings, warning shows everything. Defaults to warning. |
--format |
string | Optional. Output format: pretty or json. Defaults to pretty. |
--level only filters which issues are displayed. It never changes the exit code or the reported totals.
Folders are skipped, since they carry no content, and are excluded from the story total. When --starts-with matches no stories, the command says so rather than reporting a clean run over nothing.
Examples
Section titled “Examples”The following examples assume that a space has been defined in a configuration file.
# Validate every story against the local schemastoryblok stories validate --schema src/schema/schema.ts# Validate only the stories below a path prefixstoryblok stories validate --schema src/schema/schema.ts --starts-with "en/blog/"# Fail only on errors and hide warningsstoryblok stories validate --schema src/schema/schema.ts --level error# Emit a machine-readable reportstoryblok stories validate --schema src/schema/schema.ts --format json > stories-report.jsonOutput:
home (story #12345) ✖ missing_required_field content.headline: Missing required field "headline" on component "page". ⚠ unknown_field content.legacy_cta: Unknown field "legacy_cta" on component "page".✖ 1 error, 1 warning across 1 of 17 storiesGroups are sorted by story path, so the output of two runs over identical content is diffable.
JSON output
Section titled “JSON output”With --format json, the command writes a single JSON object to stdout and nothing else, so it can be piped or redirected. All human-facing output (the title, progress, and errors) goes to stderr.
{ "ok": false, "unit": "stories", "unitsTotal": 17, "unitsWithIssues": 1, "errors": 1, "warnings": 1, "fetchFailures": 0, "listFailed": false, "groups": [ { "header": "home (story #12345)", "ref": { "kind": "story", "id": 12345, "slug": "home", "name": "Home" }, "issues": [ { "severity": "error", "code": "missing_required_field", "path": ["content", "headline"], "entity": "block:page", "message": "Missing required field \"headline\" on component \"page\"." } ] } ]}ok is true only for a complete run with no errors. Warnings alone keep it true. But a failed listing (listFailed) or any story that could not be fetched (fetchFailures) makes it false, even with zero issues, so a CI consumer never reads success over an incomplete run. In those cases, listError and fetchErrors carry the reasons, which a consumer reading only stdout would otherwise never see.
Every group carries a ref with the machine-readable identity of the story the issues belong to. Use it instead of parsing header. The counts are always true totals, unaffected by --level.
Was this page helpful?
This site uses reCAPTCHA and Google's Privacy Policy (opens in a new window).Terms of Service (opens in a new window) apply.
Get in touch with the Storyblok community