octobercms/october · error · ValidationException
Invalid dropdown option array returned by `%s::%s`
Error message
Invalid dropdown option array returned by `%s::%s`
What it means
ValidationException thrown while parsing a snippet property's dropdown options in `Class::method` form: the referenced method was found and called, but it did not return an array. Snippet property definitions may delegate options to a static/class method, and the contract is a plain array of key => label; anything else (null, string, Eloquent Collection, object) is rejected.
Source
Thrown at modules/cms/classes/Snippet.php:277
return array_values($properties);
}
/**
* dropDownOptionsToArray
*/
protected static function dropDownOptionsToArray($optionsString)
{
if (strpos($optionsString, '::') !== false) {
$options = explode('::', $optionsString);
if (
count($options) === 2 &&
class_exists($options[0]) &&
method_exists($options[0], $options[1])
) {
$result = $options[0]::{$options[1]}();
if (!is_array($result)) {
throw new ValidationException(['snippetProperties' => sprintf(
'Invalid dropdown option array returned by `%s::%s`',
$options[0],
$options[1]
)]);
}
return $result;
}
}
$options = explode('|', $optionsString);
$result = [];
foreach ($options as $index => $optionStr) {
$parts = explode(':', $optionStr, 2);
if (count($parts) > 1) {
$key = trim($parts[0]);View on GitHub (pinned to b608633a7e)
Solutions
- Make the options method return a plain array: append `->all()` (or `->toArray()`) to Collection results.
- Declare the return type `: array` on the method so PHP itself fails fast at the source.
- Never return null/empty on error — return an empty array [] and log the cause.
Example fix
// before
class Options {
public static function getList() {
return Status::pluck('label', 'code'); // Collection, not array
}
}
// after
class Options {
public static function getList(): array {
return Status::pluck('label', 'code')->all();
}
} Defensive patterns
Strategy: type-guard
Validate before calling
// Before registering the snippet property, verify the options provider returns an array
if (strpos($options, '::') === 0 || strpos($options, '::') !== false) {
[$class, $method] = explode('::', $options, 2);
if (method_exists($class, $method) && !is_array($class::$method())) {
// fix the provider before the snippet definition ships
throw new \InvalidArgumentException("{$class}::{$method} must return an array");
}
} Type guard
/** Guarantees the 'Class::method' options provider yields a plain array. */
function assertDropdownOptionsArray(string $class, string $method): array
{
$result = $class::$method();
if (!is_array($result)) {
throw new \InvalidArgumentException("{$class}::{$method} must return array, got " . gettype($result));
}
return $result;
} Try / catch
try {
$options = Snippet::dropDownOptionsToArray($def['options']);
} catch (Winter\Storm\Exception\ValidationException $e) {
// surfaced in the editor as snippetProperties errors — point devs at the provider method
return back()->withErrors($e->getErrors());
} Prevention
- Declare `: array` return types on every options provider method.
- Convert Collections with ->all() / ->toArray() at the return statement.
- Return [] on empty/error paths instead of null.
When it happens
Trigger: Registering a snippet property with `'options' => 'MyPlugin\Classes\Options::getList'` where getList() returns null on an error path, a Laravel Collection (e.g. `pluck()` without `->all()`), or a scalar.
Common situations: Plugin authors returning Eloquent results directly instead of arrays; the method throwing/short-circuiting to null when a table is empty or a dependency is missing; refactors changing the return type.
Related errors
- Invalid drop-down option key: :key. Option keys can contain
- Document data is not provided
- cms::lang.template.invalid_type
- Invalid documentMetadata
- getDependencies() must return an array: %s
AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21).
Data as JSON: /api/errors/a9937134ef6c353a.
Report an issue: GitHub.