# Maestro YAML Parser Limitations in mobile-dev-inc/Maestro: 8 Strict Schema Constraints

> Uncover Maestro YAML parser limitations. Learn about the strict schema, command restrictions, and why it rejects unknown fields, anchors, and aliases in your mobile automation.

- Repository: [Maestro/Maestro](https://github.com/mobile-dev-inc/Maestro)
- Tags: deep-dive
- Published: 2026-03-20

---

**Maestro's YAML parser enforces a rigid whitelist-based schema that only accepts predefined commands in a specific config-then-array structure, rejecting unknown commands, extra fields, anchors, aliases, and multi-document streams without modifying the source code.**

The mobile-dev-inc/Maestro testing framework relies on a deliberately strict YAML parser that prioritizes validation over flexibility. Unlike general-purpose YAML parsers, Maestro's implementation accepts only a fixed vocabulary of commands and mandates a precise file structure. Understanding these **Maestro YAML parser limitations** is essential for writing valid flow files and troubleshooting configuration errors at the exact lines where validation fails.

## Strict Command Whitelist and Schema Validation

Maestro's parser maintains two distinct registries for command validation in [`MaestroFlowParser.kt`](https://github.com/mobile-dev-inc/Maestro/blob/main/MaestroFlowParser.kt). The `stringCommands` map (lines 59‑75) defines commands that execute as simple scalars without parameters, while the `objectCommands` list (line 57) identifies commands that require an options object. Any command name not present in these collections triggers an immediate parsing error.

### String Commands Cannot Carry Options

When the parser encounters a plain scalar command through `parseStringCommand` (lines 28‑34), it strictly validates that the command belongs to the `stringCommands` whitelist. If you attempt to write an `objectCommand` like `launchApp` as a plain scalar without its required options object, the parser throws **"Missing Command Options"** at the validation stage.

### Object Commands Require Non-Null Options

Conversely, `parseObjectCommand` (lines 65‑73) mandates that every object-based command contains a non-null options object. A null value or missing configuration for commands defined in `objectCommands` results in **"Incorrect Command Format"**. The parser further restricts command objects in lines 84‑100: after processing the command's options, it expects the end of the object, and any stray field causes **"Invalid Command Format"**.

## Mandatory File Structure Requirements

The parser enforces a rigid document structure through two critical validation points in [`MaestroFlowParser.kt`](https://github.com/mobile-dev-inc/Maestro/blob/main/MaestroFlowParser.kt). First, `parseConfig` (lines 95‑103) requires that every flow file begin with a `START_OBJECT` token representing the configuration section. If the file starts with an array or any other token, the parser immediately raises **"Config Section Required"**.

Following the config section, `parseCommands` (lines 69‑86) expects a `START_ARRAY` token. The commands section must be a YAML array containing the sequence of test steps. Missing or malformed command lists result in **"Commands Section Required"**, preventing any execution of improperly structured flows.

## Limited Command Extensibility

Unlike extensible scripting engines, Maestro's parser only recognizes command types explicitly modeled as Kotlin data classes in [`YamlFluentCommand.kt`](https://github.com/mobile-dev-inc/Maestro/blob/main/YamlFluentCommand.kt). Each supported command—such as `YamlLaunchApp`, `YamlScroll`, or `YamlTapOn`—maps to a specific field structure in this file. The parser uses these data classes during Jackson deserialization, meaning **new commands or custom extensions require direct modifications to the source code** and recompilation of the framework.

## Unsupported Standard YAML Features

The parser utilizes Jackson's `ObjectMapper(YAMLFactory)` with default settings and never enables extended features such as `YamlParser.Feature.ALLOW_ALIAS`. Consequently, standard YAML constructs including **anchors (`&`), aliases (`*`), custom tags, and complex multi-document streams** remain unsupported. This design choice ensures predictable parsing behavior but prevents users from leveraging YAML's advanced referencing capabilities to reduce repetition in flow files.

## Error Handling and Validation Boundaries

Error surfacing occurs through [`FlowParseException.kt`](https://github.com/mobile-dev-inc/Maestro/blob/main/FlowParseException.kt), which wraps parsing failures into user-facing messages. However, the parser's validation scope remains shallow: it checks command names against the whitelist and validates basic object structure through Jackson deserialization, but does not perform deep semantic validation of nested command fields beyond the initial type mapping.

## Practical Examples of Parser Constraints

### Valid Minimal Flow File

The following structure succeeds because it follows the required config-then-array pattern and uses only known commands:

```yaml
appId: com.example.app   # config section (required)

---
- launchApp               # string command without options

- tapOn:
    text: login

```

### Missing Config Section

```yaml
- launchApp

```

**Result:** `Config Section Required` (thrown at `parseConfig`, lines 95‑103).

### Unknown Command

```yaml
appId: com.example.app
---
- flyToMoon

```

**Result:** `Invalid Command: flyToMoon` (thrown in `parseStringCommand`, lines 38‑46).

### Object Command Without Options

```yaml
appId: com.example.app
---
- launchApp:

```

**Result:** `Missing Command Options` (thrown in `parseStringCommand`, lines 30‑34) because `launchApp` is listed in `objectCommands`.

### Extra Field Inside Command

```yaml
appId: com.example.app
---
- tapOn:
    text: submit
    unexpected: true

```

**Result:** `Invalid Command Format: tapOn` (thrown in `parseObjectCommand`, lines 84‑100) – the parser detects the extra top-level field `unexpected`.

## Summary

- **Whitelist enforcement:** Only commands in `stringCommands` and `objectCommands` maps within [`MaestroFlowParser.kt`](https://github.com/mobile-dev-inc/Maestro/blob/main/MaestroFlowParser.kt) are valid; all others raise immediate errors.
- **Structural rigidity:** Flow files must start with a config object (parsed by `parseConfig`) followed by a commands array (parsed by `parseCommands`).
- **Null safety:** Object commands must contain non-null options objects; null values trigger "Incorrect Command Format".
- **No extensibility:** New commands require adding data classes to [`YamlFluentCommand.kt`](https://github.com/mobile-dev-inc/Maestro/blob/main/YamlFluentCommand.kt) and updating the parser registries.
- **Limited YAML feature support:** Anchors, aliases, custom tags, and multi-document streams are disabled in the Jackson configuration.
- **Strict field validation:** Extra fields within command objects result in "Invalid Command Format" errors at `parseObjectCommand` lines 84‑100.

## Frequently Asked Questions

### Can I use YAML anchors and aliases in Maestro flow files?

No. The parser uses Jackson's `ObjectMapper(YAMLFactory)` with default settings and explicitly does not enable `YamlParser.Feature.ALLOW_ALIAS` or similar options. According to the mobile-dev-inc/Maestro source code, anchors (`&`) and aliases (`*`) are not handled by the parser, and files containing these constructs will fail validation during the initial deserialization phase.

### Why does Maestro reject my custom command names?

Maestro maintains a strict whitelist in [`MaestroFlowParser.kt`](https://github.com/mobile-dev-inc/Maestro/blob/main/MaestroFlowParser.kt) where `stringCommands` (lines 59‑75) and `objectCommands` (line 57) define the only valid command strings. The `parseStringCommand` function (lines 38‑46) throws **"Invalid Command"** errors for any name not present in these registries. Adding custom commands requires modifying [`YamlFluentCommand.kt`](https://github.com/mobile-dev-inc/Maestro/blob/main/YamlFluentCommand.kt) to define the new data class and updating the whitelist maps in the parser.

### What happens if I omit the application configuration section?

The parser raises **"Config Section Required"** through `parseConfig` at lines 95‑103 of [`MaestroFlowParser.kt`](https://github.com/mobile-dev-inc/Maestro/blob/main/MaestroFlowParser.kt). This validation enforces that the first token in the YAML stream must be `START_OBJECT` (the config section). Flow files beginning directly with a commands array or any other structure fail immediately before command parsing begins.

### Can I add optional parameters to existing Maestro commands through YAML alone?

No. The parser validates command structure against immutable Kotlin data classes in [`YamlFluentCommand.kt`](https://github.com/mobile-dev-inc/Maestro/blob/main/YamlFluentCommand.kt). While some commands accept optional fields defined in their data class, you cannot introduce new parameters or fields through YAML configuration alone. Attempting to add unrecognized fields results in **"Invalid Command Format"** errors from `parseObjectCommand` (lines 84‑100), as the parser rejects any object containing fields not explicitly modeled in the source code.