{"record":{"id":"beaf1fc12852092d","repo":"flarum/framework","slug":"fields-must-be-an-array","errorCode":null,"errorMessage":"fields must be an array","messagePattern":"fields must be an array","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"framework/core/src/Http/RequestUtil.php","lineNumber":238,"sourceCode":"    }\n\n    public static function extractFilter(Request $request): array\n    {\n        $filter = $request->getQueryParams()['filter'] ?? [];\n\n        if (! is_array($filter)) {\n            throw new BadRequestException('filter must be an array');\n        }\n\n        return $filter;\n    }\n\n    public static function extractFields(Request $request, ?array $available = null): array\n    {\n        $fields = $request->getQueryParams()['fields'] ?? [];\n\n        if (! is_array($fields)) {\n            throw new BadRequestException('fields must be an array');\n        }\n\n        if ($available !== null) {\n            $invalid = array_diff(array_keys($fields), $available);\n\n            if (count($invalid)) {\n                throw new BadRequestException('Invalid fields ['.implode(',', $invalid).']');\n            }\n        }\n\n        return $fields;\n    }\n}\n","sourceCodeStart":220,"sourceCodeEnd":252,"githubUrl":"https://github.com/flarum/framework/blob/4b939f685389bfe8a380e9e28ddf305a1c66950c/framework/core/src/Http/RequestUtil.php#L220-L252","documentation":"RequestUtil::extractFields() reads the 'fields' query parameter used for sparse fieldset filtering. If the client sends ?fields= as a non-array value (a plain string instead of field => array pairs), the method rejects it with BadRequestException because per-field selections must be structured as arrays.","triggerScenarios":"Calling extractFields() on a request whose query string is e.g. ?fields=name,email (bare string) instead of ?fields[users]=name,email; any GET where 'fields' resolves to a scalar via $request->getQueryParams().","commonSituations":"API clients hand-building query strings without PHP array bracket syntax; copying examples that flatten fields into a comma list; proxies or gateways dropping the square brackets from fields[...] parameters.","solutions":["Change the client to send fields as sub-arrays: ?fields[users]=name,email","Wrap the call in try-catch and return a 400 response guiding the client to the correct format","Pre-normalize the query param in middleware so a string 'fields' is converted or rejected before reaching extractFields"],"exampleFix":"// before\nGET /api/posts?fields=title,body\n// after\nGET /api/posts?fields[posts]=title,body","handlingStrategy":"type-guard","validationCode":"$fields = $request->getQueryParams()['fields'] ?? null;\nif ($fields !== null && ! is_array($fields)) {\n    throw new BadRequestException('fields must be an array of field => value pairs');\n}","typeGuard":"function isStringKeyedArray($v): bool { return is_array($v) && (array_is_list($v) ? $v === [] : true) && $v === [] || (is_array($v) && ! array_is_list($v)); }","tryCatchPattern":"try {\n    $fields = RequestUtil::extractFields($request, $available);\n} catch (BadRequestException $e) {\n    return response()->json(['error' => 'fields must be sent as ?fields[type]=a,b'], 400);\n}","preventionTips":["Always send sparse fieldsets as ?fields[type]=a,b with array bracket syntax","Document the expected fields format in your API client library","Add integration tests asserting 400 responses for malformed fields params"],"tags":["http","query-parameters","bad-request","validation"],"backgroundTag":"invalid-query-parameter","analyzedSha":"4b939f685389bfe8a380e9e28ddf305a1c66950c","analyzedAt":"2026-09-15T18:09:20.879Z","contentChangedAt":"2026-09-15T18:09:20.879Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}