> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getflowpilot.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Schema versions

> The two FlowPilot version counters, the editor migration chain, and what unsupportedSchemaVersion means on the SDK.

FlowPilot tracks two different version numbers. Keeping them straight avoids confusion when you read a flow or debug a resolve response.

## Two version counters

| Counter                   | Where it lives                                                                    | Current value | Purpose                                                                             |
| ------------------------- | --------------------------------------------------------------------------------- | ------------- | ----------------------------------------------------------------------------------- |
| Content/migration version | The `version` field inside the flow JSON (`CURRENT_SCHEMA_VERSION` in the editor) | `9`           | Tracks editor-side schema shape changes. Old flows migrate forward to this on load. |
| Wire format version       | The `schema_version` field on a flow version (and in the resolve response)        | `1`           | The compatibility gate the SDK checks. A major bump means the wire format changed.  |

The content version is bumped by the editor's migrations as the component model evolves. The wire format version stays at `1` because the on-the-wire JSON shape the SDK parses has not changed in a way that breaks older SDKs. They are not the same number, and that is expected.

## Editor migrations (content version)

When the editor loads a flow whose `version` is below `9`, it applies migrations in sequence until it reaches the current version. Each migration is small and runs on load (never on save unless you then save the draft).

| From | To | What it does                                                                                                                                                                                      |
| ---- | -- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1    | 2  | Rename Chrome to Persistent UI zones (Navigation Bar, Footer, Overlay).                                                                                                                           |
| 2    | 3  | Merge checkbox into toggle as a variant.                                                                                                                                                          |
| 3    | 4  | Strip removed component nodes (`carousel`, `video`, `lottie`, `chart`, `spacer`, `divider`).                                                                                                      |
| 4    | 5  | Unwind the checkbox toggle-variant: re-ship checkbox as a Block (stack + icon + text).                                                                                                            |
| 5    | 6  | Unify the button's style surface with the stack's (canonical `justify`/`align`/`padding`/`cornerRadius`/`width`/`spacing`/`text`/`color`).                                                        |
| 6    | 7  | Collapse the `card` primitive into a styled stack (surface defaults merged).                                                                                                                      |
| 7    | 8  | Collapse the `chip` primitive into a styled stack (capsule + text child + onPress selection).                                                                                                     |
| 8    | 9  | Derive and store the full theme-token color palette in `globalStyles.colors` (the editable core colors expand to the complete token set the editor and SDKs resolve `token:` references against). |

If a flow is somehow ahead of the migration registry (no migration path found), the editor logs a warning and stamps it as the current version without transforming it.

### Removed and rewritten types

Migrations strip or rewrite types that are no longer in the schema:

* Stripped from the layout tree on load: `carousel`, `video`, `chart`, `spacer`, `divider` (and the old placeholder `lottie`). The parent stays; only the removed node and its descendants go.
* Rewritten into a composition of current primitives: `checkbox` and `chip` become styled stacks; `card` becomes a styled stack with surface defaults; legacy button-only prop names map to the canonical ones.

<Note>
  `lottie` and `comparisonChart` are supported component kinds in the current schema. The strip in the 3 to 4 migration applied to the earlier placeholder versions of these kinds; the real primitives were added later. See the [Component reference](/reference/component-reference) for the current list.
</Note>

## SDK compatibility (wire format version)

Both SDKs check the resolve response's `schema_version` against the highest version they support (`1.0.0` in the current iOS and Expo SDKs). They compare the **major** component only.

* Same major version: the flow renders. If the minor or patch is newer than the SDK, the SDK renders best-effort and logs a warning. Any component or node type the build does not recognize is skipped rather than failing the whole screen.
* Higher major version: the SDK throws `unsupportedSchemaVersion` with the message "Flow requires schema X, but SDK only supports up to Y. Please update the app." This is the signal that the wire format changed in a way the installed SDK genuinely cannot parse.

This is why additive changes (new component kinds, new props) are safe for old apps: they fall under the same major version and are skipped if unknown. A major bump is reserved for breaking format changes and would require an app update.

An unsupported schema version is one of the error codes a FlowPilot SDK can surface (`unsupportedSchemaVersion` on iOS, `UNSUPPORTED_SCHEMA_VERSION` on Expo). See error handling for [iOS](/ios-sdk/error-handling) or [Expo](/expo-sdk/error-handling) for how each delivers it (the iOS never-throwing overloads return it as a `FlowResult` error rather than throwing).

## Notes

* The migration chain is what lets you publish over many months without breaking old drafts: opening an old flow upgrades it in the editor.
* The exact per-version field-level changes beyond the descriptions above are not enumerated here; the migration descriptions above are taken verbatim from the migration registry.

## Related pages

* [Flow schema reference](/reference/flow-schema)
* [Error handling (iOS SDK)](/ios-sdk/error-handling)
* [Error handling (Expo SDK)](/expo-sdk/error-handling)
