phalcon/cphalcon · error · Phalcon\Forms\Exceptions\SchemaEntryNotArray

Form schema definition at index {index} must be an array

Error message

Form schema definition at index {index} must be an array

What it means

Phalcon\Forms\Loader\ArrayLoader validates every schema entry via validateDefinition(); the first check requires the definition at each index to be a PHP array. Anything else at that index — a string, int, null, or stdClass — throws SchemaEntryNotArray with the failing index, because element definitions must be key/value maps.

Source

Thrown at phalcon/Forms/Loader/ArrayLoader.zep:60

        var definition, index;

        for index, definition in this->definitions {
            this->validateDefinition(definition, (int) index);
        }

        return this->definitions;
    }

    /**
     * @param mixed $definition
     * @param int   $index
     *
     * @throws Exception
     */
    protected function validateDefinition(var definition, int index) -> void
    {
        if typeof definition !== "array" {
            throw new SchemaEntryNotArray(index);
        }

        if !isset definition["type"] || empty definition["type"] {
            throw new SchemaEntryMissingKey(index, "type");
        }

        if !isset definition["name"] || empty definition["name"] {
            throw new SchemaEntryMissingKey(index, "name");
        }
    }
}

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Ensure every entry of the definitions list is itself an array (starts with '[' / '- ' in YAML)
  2. Decode JSON with assoc=true so nested documents become arrays, not stdClass
  3. Map objects to arrays before constructing the loader: $definitions = array_map(fn($d) => (array) $d, $definitions)

Example fix

// before
$loader = new ArrayLoader([
    ['type' => 'text', 'name' => 'email'],
    'submit', // string, not an array
]);

// after
$loader = new ArrayLoader([
    ['type' => 'text', 'name' => 'email'],
    ['type' => 'submit', 'name' => 'send'],
]);
Defensive patterns

Strategy: validation

Validate before calling

$invalid = [];
foreach ($definitions as $index => $definition) {
    if (!is_array($definition)) {
        $invalid[] = $index;
    }
}

if ($invalid !== []) {
    throw new \InvalidArgumentException(
        'Schema entries must be arrays; bad indexes: ' . implode(', ', $invalid)
    );
}

$formDefs = (new \Phalcon\Forms\Loader\ArrayLoader($definitions))->load();

Type guard

/** @param mixed $definition */
function isSchemaEntry($definition): bool
{
    return is_array($definition);
}

Try / catch

try {
    $defs = (new \Phalcon\Forms\Loader\ArrayLoader($definitions))->load();
} catch (\Phalcon\Forms\Exceptions\SchemaEntryNotArray $e) {
    // the message names the offending index; surface it to the config author
    throw new \RuntimeException('Bad form schema: ' . $e->getMessage(), 0, $e);
}

Prevention

When it happens

Trigger: new ArrayLoader($definitions)->load() where $definitions[3] is a scalar or stdClass; JSON decoded without assoc=true producing stdClass rows; YAML entries that parse to plain strings.

Common situations: Hand-written schema arrays with a stray quoted entry; feeding mixed data from an API; a custom loader that skips the assoc flag when decoding.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21). Data as JSON: /api/errors/d8fe9e3873c18c66. Report an issue: GitHub.