{"record":{"id":"a9937134ef6c353a","repo":"octobercms/october","slug":"invalid-dropdown-option-array-returned-by-s-s","errorCode":null,"errorMessage":"Invalid dropdown option array returned by `%s::%s`","messagePattern":"Invalid dropdown option array returned by `(.+?)::(.+?)`","errorType":"validation","errorClass":"ValidationException","httpStatus":null,"severity":"error","filePath":"modules/cms/classes/Snippet.php","lineNumber":277,"sourceCode":"\n        return array_values($properties);\n    }\n\n    /**\n     * dropDownOptionsToArray\n     */\n    protected static function dropDownOptionsToArray($optionsString)\n    {\n        if (strpos($optionsString, '::') !== false) {\n            $options = explode('::', $optionsString);\n            if (\n                count($options) === 2 &&\n                class_exists($options[0]) &&\n                method_exists($options[0], $options[1])\n            ) {\n                $result = $options[0]::{$options[1]}();\n                if (!is_array($result)) {\n                    throw new ValidationException(['snippetProperties' => sprintf(\n                        'Invalid dropdown option array returned by `%s::%s`',\n                        $options[0],\n                        $options[1]\n                    )]);\n                }\n\n                return $result;\n            }\n        }\n\n        $options = explode('|', $optionsString);\n\n        $result = [];\n        foreach ($options as $index => $optionStr) {\n            $parts = explode(':', $optionStr, 2);\n\n            if (count($parts) > 1) {\n                $key = trim($parts[0]);","sourceCodeStart":259,"sourceCodeEnd":295,"githubUrl":"https://github.com/octobercms/october/blob/b608633a7e8922487d91a8161499020121c3b3bf/modules/cms/classes/Snippet.php#L259-L295","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nclass Options {\n    public static function getList() {\n        return Status::pluck('label', 'code'); // Collection, not array\n    }\n}\n\n// after\nclass Options {\n    public static function getList(): array {\n        return Status::pluck('label', 'code')->all();\n    }\n}","handlingStrategy":"type-guard","validationCode":"// Before registering the snippet property, verify the options provider returns an array\nif (strpos($options, '::') === 0 || strpos($options, '::') !== false) {\n    [$class, $method] = explode('::', $options, 2);\n    if (method_exists($class, $method) && !is_array($class::$method())) {\n        // fix the provider before the snippet definition ships\n        throw new \\InvalidArgumentException(\"{$class}::{$method} must return an array\");\n    }\n}","typeGuard":"/** Guarantees the 'Class::method' options provider yields a plain array. */\nfunction assertDropdownOptionsArray(string $class, string $method): array\n{\n    $result = $class::$method();\n    if (!is_array($result)) {\n        throw new \\InvalidArgumentException(\"{$class}::{$method} must return array, got \" . gettype($result));\n    }\n    return $result;\n}","tryCatchPattern":"try {\n    $options = Snippet::dropDownOptionsToArray($def['options']);\n} catch (Winter\\Storm\\Exception\\ValidationException $e) {\n    // surfaced in the editor as snippetProperties errors — point devs at the provider method\n    return back()->withErrors($e->getErrors());\n}","preventionTips":["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."],"tags":["snippet","editor","return-type","dropdown","api-contract"],"backgroundTag":"invalid-return-type","analyzedSha":"b608633a7e8922487d91a8161499020121c3b3bf","analyzedAt":"2026-08-21T04:24:57.515Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}