{"record":{"id":"cb2230accef8adfe","repo":"flarum/framework","slug":"request-must-be-limited-to-presence-channels-in-order-to","errorCode":null,"errorMessage":"Request must be limited to presence channels in order to fetch user_count","messagePattern":"Request must be limited to presence channels in order to fetch user_count","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"extensions/realtime/src/Websocket/Connection/FetchChannels.php","lineNumber":30,"sourceCode":"use Flarum\\Realtime\\Websocket\\Channel\\Channel;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Str;\nuse Psr\\Http\\Message\\ServerRequestInterface;\nuse stdClass;\nuse Symfony\\Component\\HttpFoundation\\Exception\\BadRequestException;\n\nclass FetchChannels extends Controller\n{\n    public function __invoke(ServerRequestInterface $request): mixed\n    {\n        $attributes = [];\n        $filterByPrefix = Arr::get($request->getQueryParams(), 'filter_by_prefix');\n\n        if ($info = Arr::get($request->getQueryParams(), 'info')) {\n            $attributes = explode(',', trim($info));\n\n            if (in_array('user_count', $attributes) && ! Str::startsWith($filterByPrefix, 'presence-')) {\n                throw new BadRequestException('Request must be limited to presence channels in order to fetch user_count');\n            }\n        }\n\n        return $this->manager\n            ->getChannels()\n            ->then(function ($channels) use ($filterByPrefix, $attributes) {\n                /** @phpstan-ignore-next-line */\n                $channels = collect($channels)\n                    ->mapWithKeys(function ($channel) {\n                        $key = $channel instanceof Channel\n                            ? $channel->getName()\n                            : $channel;\n\n                        return [\n                            $key => new stdClass\n                        ];\n                    });\n","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/flarum/framework/blob/4b939f685389bfe8a380e9e28ddf305a1c66950c/extensions/realtime/src/Websocket/Connection/FetchChannels.php#L12-L48","documentation":"Validation guard in the realtime websocket FetchChannels controller. The 'info' query parameter (comma-separated channel attributes) may only request user_count for presence channels; the request named non-presence channels in its prefix filter, which cannot provide per-user counts, so the controller rejects it with a BadRequestException instead of returning incomplete data.","triggerScenarios":"Thrown at extensions/realtime/src/Websocket/Connection/FetchChannels.php:30 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Only pass filter_by_prefix values that match presence channels (e.g. 'presence-') when requesting info=user_count.","Drop user_count from the info parameter if non-presence channels must be fetched.","If the client derives the prefix dynamically, filter the channel list to presence-* before sending the request.","Wrap the call in try-catch on the client side and surface a clear message that user_count requires presence channels."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"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"}