Skip to content

Navigation Menu

Sign in
Sign up

Why doesn't my subscription work? #2636

Unanswered
omega-uo asked this question in Q&A
Nov 29, 2024 · 4 comments · 4 replies
Discussion options

Hi, I'm a complete beginner, unfortunately with Laravel, also with Lighthouse, and with Pusher. I want to develop a mobile app with Flutter that should communicate with a Laravel backend via graphQL. The queries and mutations work. Subscriptions don't work at all, no matter what I do. Can anyone give me a tip?

Currently I am trying to get the following configuration to work:
First, I created a completely new laravel project, via:

composer create-project laravel/laravel laravel-lighthouse-pusher-subscription
composer require nuwave/lighthouse
php artisan vendor:publish --tag=lighthouse-schema
php artisan lighthouse:ide-helper
php artisan vendor:publish --tag=lighthouse-config
composer require pusher/pusher-php-server
composer require mll-lab/laravel-graphiql
php artisan vendor:publish --tag=graphiql-config
php artisan graphiql:download-assets

I've added Nuwave\Lighthouse\Subscriptions\SubscriptionServiceProvider::class, in bootstrap\providers.php.

I've created two models, author and blog, as well as a, in my opinion, suitable scheme:

type Query {
 authors: [Author!]! @all
 blogs: [Blog!]! @all }
type Mutation {
 createBlog(input: CreateBlogInput! @spread): Blog! @broadcast(subscription: "blogInserted") @create }
type Subscription {
 blogInserted: Blog }
input CreateBlogInput {
 title: String!
 content: String!
 author: CreateAuthorBelongsTo }
input CreateAuthorBelongsTo {
 connect: ID
 create: CreateAuthorInput }
input CreateAuthorInput {
 name: String! }
type Blog {
 id: ID!
 title: String!
 content: String!
 author: Author!
 created_at: DateTime!
 updated_at: DateTime! }
type Author {
 id: ID!
 name: String!
 created_at: DateTime!
 updated_at: DateTime!
 blogs: [Blog!]! }

In .env I defined the pusher variables:

PUSHER_APP_ID="..."
PUSHER_APP_KEY="..."
PUSHER_APP_SECRET="..."
PUSHER_HOST=
PUSHER_PORT=443
PUSHER_APP_CLUSTER="eu"
PUSHER_USE_TLS=true
PUSHER_SCHEME=https
BROADCAST_CONNECTION=pusher
BROADCAST_DRIVER=pusher
LIGHTHOUSE_BROADCASTER=pusher

The mutation:

mutation {
 createBlog(input: { title: "hohoho", content: "hohoho",author: {connect: "2"} }) {
 id
 title } }

works. It always creates a new record in the database. The job Nuwave\Lighthouse\Subscriptions\BroadcastSubscriptionJob is queued and is executed shortly afterwards. There are no errors in the laravel.log. But nothing appears in the pusher debug console.

Before that, I start the subscription:

subscription {
 blogInserted {
 id
 title } }

in the hope that this will notify me of the new blog-entry. Nothing happens via the Altair GraphQL client. This request also does not arrive in the pusher debug console. Via graphiQL, the connection breaks immediately or is not established at all, the error message is: "errors": [ { "isTrusted": true } ]

The functions authorize and filter of class BlogInserted (extends GraphQLSubscription) returns constant true.

Because I'm not sure, I'm testing with two different subscriptions URLs:
a.) GRAPHIQL_SUBSCRIPTION_ENDPOINT="ws://127.0.0.1:8801/graphql"
b.) GRAPHIQL_SUBSCRIPTION_ENDPOINT="wss://ws-${PUSHER_APP_CLUSTER}.pusher.com:443/app/${PUSHER_APP_KEY}?protocol=7"

Does anyone have an idea how I can find my mistake?

You must be logged in to vote

Replies: 4 comments 4 replies

Comment options

To get your Laravel + Lighthouse + Pusher subscription setup working with Flutter, it's important to ensure all components are properly configured and compatible. Based on your detailed description, here are some common issues and their solutions:

  1. WebSocket Server for Lighthouse Subscriptions
    Lighthouse requires a WebSocket server to handle GraphQL subscriptions. Laravel does not natively support WebSocket handling, so you'll need to set up a WebSocket server, such as:

Laravel WebSocket Package:

composer require beyondcode/laravel-websockets php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="config"
Update the .env file:

PUSHER_APP_ID=local PUSHER_APP_KEY=local PUSHER_APP_SECRET=local PUSHER_APP_CLUSTER=mt1 Update your broadcasting.php:

'pusher' => [ 'driver' => 'pusher', 'key' => env('PUSHER_APP_KEY'), 'secret' => env('PUSHER_APP_SECRET'), 'app_id' => env('PUSHER_APP_ID'), 'options' => [ 'cluster' => env('PUSHER_APP_CLUSTER'), 'useTLS' => false, 'host' => '127.0.0.1', 'port' => 6001, 'scheme' => 'http', ], ],

Start the WebSocket server:

php artisan websockets:serve
Lighthouse will now use the WebSocket server for subscriptions.

  1. Ensure Pusher Configuration Matches
    The Lighthouse and Pusher configurations must align with the WebSocket server setup. Double-check the LIGHTHOUSE_BROADCASTER and PUSHER_* environment variables. Use the following GRAPHIQL_SUBSCRIPTION_ENDPOINT for local testing:

GRAPHIQL_SUBSCRIPTION_ENDPOINT="ws://127.0.0.1:6001/graphql"

If you're deploying to production, use:
GRAPHIQL_SUBSCRIPTION_ENDPOINT="wss://your-websocket-server/graphql"

  1. Broadcasting Setup
    Ensure you’ve set up broadcasting correctly in Laravel. Run the following command to generate the broadcasting configuration:

php artisan queue:work

Then, verify that jobs are being dispatched and processed. Check jobs table logs if you're using the database queue.

  1. Verify Lighthouse Subscription Class
    The subscription resolver class should correctly implement the GraphQLSubscription interface. For instance:

namespace App\GraphQL\Subscriptions;

use Nuwave\Lighthouse\Subscriptions\GraphQLSubscription;

class BlogInserted extends GraphQLSubscription
`{
public function authorize($rootValue, array $args, $context)
{
return true; // Ensure this returns true
}

public function filter($rootValue, array $args, $context)
{
 return true; // Ensure this returns true
}

}`

Ensure you’ve registered this subscription in the lighthouse.php config.

  1. Altair GraphQL Client
    Altair often disconnects if the WebSocket configuration is incorrect. Confirm you're using the correct URL:

For local:

ws://127.0.0.1:6001/graphql

For production (Pusher):

wss://ws-${PUSHER_APP_CLUSTER}.pusher.com/app/${PUSHER_APP_KEY}?protocol=7

  1. Debugging Tips
    Check WebSocket Connection: Use browser developer tools or WebSocket testing tools to verify the WebSocket connection.
    Inspect Pusher Console: If nothing shows in the Pusher console, the connection between Laravel and Pusher might not be established.
    Enable Laravel Debugging: Temporarily set APP_DEBUG=true in .env and inspect logs.

Manually Test Events: Test Pusher by broadcasting a manual event to see if it reaches the Pusher console:

event(new \App\Events\BlogCreated($blog));

  1. Consider Flutter Integration
    On the Flutter side, use the graphql_flutter package to implement GraphQL subscriptions. Ensure the subscription endpoint matches the backend configuration.

Example:

final HttpLink httpLink = HttpLink('http://localhost/graphql'); final WebSocketLink websocketLink = WebSocketLink('ws://localhost:6001/graphql');

Combine them:

final Link link = Link.split( (request) => request.isSubscription, websocketLink, httpLink, );

Conclusion
Follow these steps to troubleshoot and configure your setup. Start with the WebSocket server, verify broadcasting and subscription configurations, and test manually. If issues persist, share specific logs or errors for further assistance.

You must be logged in to vote
3 replies
Comment options

Thank you very much for your detailed response ! I'm really looking forward to applying the tips and will report back here about my results. Thank you again for your help !

Comment options

In the meantime, I was able to continue working on this problem. Thanks again for your advice. Unfortunately, I haven't made any progress yet.

I couldn't install the package: beyondcode/laravel-websockets. Various dependencies always prevented this. The latest release 1.14.1 is from August 30, 2023 and doesn't work with my more recent Laravel installation. Beyondcode has stopped further development and refers to reverb.

Then I tried reverb. I installed it with:
php artisan install:broadcasting

Then I set the following .env parameters:
LIGHTHOUSE_SUBSCRIPTION_STORAGE="database"
LIGHTHOUSE_BROADCASTER="reverb"
GRAPHIQL_SUBSCRIPTION_ENDPOINT="ws://127.0.0.1:8099/graphql"
REVERB_APP_ID=883890
REVERB_APP_KEY=vn7cgn0g6p87veynhzsq
REVERB_APP_SECRET=cynaqy5qubdlioly3lec
REVERB_HOST="localhost"
REVERB_PORT=8099
REVERB_SCHEME=http
REVERB_SERVER_PORT="${REVERB_PORT}"

Then I started the websocket server with "php artisan reverb:start" and ran "php artisan queue:work".

If I now want to register the subscription with graphiQL, using the graphql query:
"subscription MySubscription {blogInserted {id}}"
, I get the following error message:
"Your GraphiQL createFetcher is not properly configured for websocket subscriptions yet. Please provide subscriptionUrl, wsClient or legacyClient option first."

Maybe the value "GRAPHIQL_SUBSCRIPTION_ENDPOINT="ws://127.0.0.1:8099/graphql"" is wrong, but how do I find the correct value ?

If I insert a record regardless, appears in the queue:
2025年01月20日 15:09:31 Nuwave\Lighthouse\Subscriptions\BroadcastSubscriptionJob ................................................................. RUNNING
2025年01月20日 15:09:31 Nuwave\Lighthouse\Subscriptions\BroadcastSubscriptionJob ............................................................ 73.56ms DONE

And there is nothing about this in the output of the websocketserver reverb.

Do you have another tip for me?

Comment options

  1. Ensure Proper Configuration for Reverb
    Reverb is the recommended alternative to beyondcode/laravel-websockets and needs correct setup in your .env file. Based on your configuration:

Check These Points:

Ensure the WebSocket server is running on the specified port:

php artisan reverb:start
Double-check your .env values:

REVERB_HOST="127.0.0.1" # Use IP instead of localhost if unsure.
REVERB_PORT=8099
REVERB_SCHEME=http
LIGHTHOUSE_BROADCASTER="reverb"
LIGHTHOUSE_SUBSCRIPTION_STORAGE="database"
GRAPHIQL_SUBSCRIPTION_ENDPOINT="ws://127.0.0.1:8099/graphql"
Verify WebSocket Server Logs: Run php artisan reverb:start and observe its output for startup errors.

  1. GraphiQL Subscription Configuration
    GraphiQL requires an explicit WebSocket setup for subscriptions. To resolve the createFetcher error:

Solution: Edit the config/graphiql.php to define the WebSocket URL. For example:

'subscription_url' => env('GRAPHIQL_SUBSCRIPTION_ENDPOINT', 'ws://127.0.0.1:8099/graphql'),
Then, set the GRAPHIQL_SUBSCRIPTION_ENDPOINT in .env:

GRAPHIQL_SUBSCRIPTION_ENDPOINT="ws://127.0.0.1:8099/graphql"
Restart Services: After making changes, restart the WebSocket server and queue workers:

php artisan reverb:start
php artisan queue:work
3. Database and Queue Integration
Verify that the database and queue systems are correctly set up for Lighthouse to store and dispatch subscription events.

Ensure Tables Are Migrated: Run migrations for the required tables:

php artisan migrate
Queue Worker: Ensure your queue worker is running and processing jobs correctly:

php artisan queue:work
4. Debug WebSocket Server and Client
To confirm that the server is operational and the client can connect:

Test the WebSocket Connection: Use a WebSocket client like wscat to connect to the Reverb WebSocket server:

wscat -c ws://127.0.0.1:8099/graphql
If the connection fails, there may be an issue with the server setup.

Enable Debug Logs: Modify your .env file to enable debugging:

APP_DEBUG=true
LOG_CHANNEL=stack
Manually Trigger Subscriptions: Broadcast a test event using the Laravel broadcast helper:

event(new \Nuwave\Lighthouse\Subscriptions\Events\BroadcastSubscription($data));
5. Verify Flutter Integration
If your Laravel backend works correctly, but your Flutter app is still not receiving updates, check:

The graphql_flutter configuration.
Ensure the WebSocket endpoint matches ws://127.0.0.1:8099/graphql.
Sample Setup:

final httpLink = HttpLink('http://localhost/graphql');
final websocketLink = WebSocketLink('ws://127.0.0.1:8099/graphql');

final link = Link.split(
(request) => request.isSubscription,
websocketLink,
httpLink,
);

  1. Test Alternative Lighthouse Broadcasters
    If Reverb does not work as expected, consider using other broadcasters, such as Pusher or Ably. Update the LIGHTHOUSE_BROADCASTER and test their integration.

Debug Checklist
Is the WebSocket server running and accessible at ws://127.0.0.1:8099?
Are queue jobs processing successfully (no failed jobs in the database)?
Can you see any WebSocket activity in the Reverb logs when you create a new blog?
If these steps don't resolve your issue, sharing specific errors or logs from Reverb and Laravel will help diagnose further.

Comment options

I tried to implement your tips, including insert 'subscription_url' into "config/graphiql.php"

Now when I try to register the subscription with graphiql, the error message "{ "errors": [ {"isTrusted": true} ] }" appears.

I always start the reverb server with:
php artisan reverb:start --debug

At no time do error messages appear in the output. From my point of view, the reverb server is working properly.
"APP_DEBUG=true", "LOG_CHANNEL=stack", "LOG_LEVEL=debug" is always set.

But the result of
wscat -c ws://127.0.0.1:8099/graphql
is
error: Unexpected server response: 404

I have to use the following URL:
wscat -c "ws://127.0.0.1:8099/app/zbtonb7eoebrcbzi5rfi"
(the string "zbtonb7eoebrcbzi5rfi" is the REVERB_APP_KEY)
to get back:
{"event":"pusher:connection_established","data":"{"socket_id":"52336590.360144190","activity_timeout":30}"}

but also with
GRAPHIQL_SUBSCRIPTION_ENDPOINT="ws://127.0.0.1:8099/app/zbtonb7eoebrcbzi5rfi"
I get the error message "{ "errors": [ {"isTrusted": true} ] }"

When I create a new blog, the following happens
1.) I see the new blog in the database
2.) the queue worker performs successfully a new job "Nuwave\Lighthouse\Subscriptions\BroadcastSubscriptionJob"
3.) no entry in the laravel log
4.) no entry in the reverb output
I suspect that the reverb server needs the subscription first.

I tried to access the reverb server via a livewire/echo app instead of lighthouse/graphql. That works. But then I wouldn't be able to use lighthouse broadcasting at all.

Do you have another tip for me?

You must be logged in to vote
0 replies
Comment options

Now I have made another attempt.

When I use "GRAPHIQL_SUBSCRIPTION_ENDPOINT="ws://127.0.0.1:8099/app/zbtonb7eoebrcbzi5rfi"" and starts the graphql-query to register the subscription, appears in the reverb-output: "Connection Established ..... 276975131.803874006" and "Connection Closed ..... 276975131.803874006".

But in the end it remains with the error message "{ "errors": [ {"isTrusted": true} ] }".

Propably it's only a java script error, because the client can't parse the error-message or there is a empty message. At least that's what I got from this link:
https://stackoverflow.com/questions/44815172/log-shows-error-object-istrustedtrue-instead-of-actual-error-data

While I run the "Subscription registration" test in graphiql, an empty websocket response appears in the chrome developer tool.

You must be logged in to vote
1 reply
Comment options

To resolve the issues with your Laravel + Lighthouse + Reverb WebSocket subscription setup, let’s address each potential problem systematically:

Key Observations
Reverb Server Connection Issues
You successfully connected using wscat with the URL format:
ws://127.0.0.1:8099/app/${REVERB_APP_KEY}
This confirms that the Reverb server is running but requires the correct URL for authentication.

GraphiQL Error (errors: [{ "isTrusted": true }])
This error often indicates a failure in handling the WebSocket connection or parsing server responses.

Broadcast Subscription Not Reaching Reverb
Despite successful job execution, Reverb does not log the subscription or handle events, likely due to mismatched configuration.

Action Plan

  1. Verify Reverb Server Setup
    Ensure the Reverb server is properly configured to handle subscriptions:

Check .env Settings:

REVERB_HOST="127.0.0.1"
REVERB_PORT=8099
REVERB_SCHEME=http
REVERB_APP_KEY=zbtonb7eoebrcbzi5rfi
REVERB_APP_SECRET=your-app-secret
LIGHTHOUSE_BROADCASTER="reverb"
LIGHTHOUSE_SUBSCRIPTION_STORAGE="database"
GRAPHIQL_SUBSCRIPTION_ENDPOINT="ws://127.0.0.1:8099/app/${REVERB_APP_KEY}"

Start Reverb in Debug Mode:
php artisan reverb:start --debug

  1. Correct Subscription Endpoint for GraphiQL
    Update config/graphiql.php to use the correct WebSocket URL:

'subscription_url' => env('GRAPHIQL_SUBSCRIPTION_ENDPOINT', 'ws://127.0.0.1:8099/app/zbtonb7eoebrcbzi5rfi'),
Restart the Reverb server and try registering the subscription.

  1. Handle WebSocket 404 Errors
    If you encounter a 404 error using wscat or in GraphiQL, ensure the Reverb server is configured to recognize the /graphql route.

Check Lighthouse Configuration: Lighthouse must correctly forward subscription queries to the broadcaster:

Open config/lighthouse.php and verify:
'subscriptions' => [
'storage' => env('LIGHTHOUSE_SUBSCRIPTION_STORAGE', 'database'),
'broadcaster' => env('LIGHTHOUSE_BROADCASTER', 'reverb'),
'path' => 'graphql',
],
Ensure the graphql route is registered in routes/graphql.php:
use Nuwave\Lighthouse\Support\Http\Controllers\GraphQLController;
Route::post('/graphql', [GraphQLController::class, 'query']);
Route::webSockets('/graphql', [GraphQLController::class, 'webSocket']);

  1. Inspect Laravel Logs
    Enable verbose logging to capture any issues during subscription handling:

APP_DEBUG=true
LOG_CHANNEL=stack
LOG_LEVEL=debug
Restart Laravel services:

php artisan reverb:start --debug
php artisan queue:work
5. Test Subscription Flow
Manually test if Reverb receives subscription events:

Register a subscription using Altair or GraphiQL:

subscription {
blogInserted {
id
title
}
}

Insert a new blog:
mutation {
createBlog(input: { title: "Test Blog", content: "Content", author: { connect: "1" } }) {
id
title
}
}

Verify:
Reverb server logs show the subscription.
Laravel queue worker logs the BroadcastSubscriptionJob.

  1. Debug Client-Side JavaScript
    The errors: [{ "isTrusted": true }] issue might stem from client-side code failing to parse the server response. This could happen due to:

Incorrect subscription endpoint.
Missing or malformed WebSocket responses.
Check Chrome DevTools (Network → WS) for any errors or empty responses. Ensure Reverb is properly responding to subscription requests.

Advanced Debugging
If the issue persists:

Inspect Reverb Logs: Run php artisan reverb:start --debug and monitor output during subscriptions.
Test Direct Pusher Integration: If Reverb fails, fallback to testing with Pusher directly.
Simplify Lighthouse Setup: Use a minimal schema to isolate the subscription functionality and ensure it works end-to-end.
Flutter Integration
Once backend subscriptions work, configure graphql_flutter to handle subscriptions:

final httpLink = HttpLink('http://localhost/graphql');
final websocketLink = WebSocketLink(
'ws://127.0.0.1:8099/app/zbtonb7eoebrcbzi5rfi',
);

final link = Link.split(
(request) => request.isSubscription,
websocketLink,
httpLink,
);

Comment options

First of all, thank you very much again for your patient support!

And I have a question about your last post:
There is no "routes/graphql.php", only "routes/channels.php", "routes/console.php", "routes/web.php" ???

But route:list nevertheless shows:

GET|POST|HEAD graphql ....................................... graphql › Nuwave\Lighthouse › GraphQLController

and the base data for this route stands in config/lighthouse.php
'route' => [
'uri' => '/graphql',
'name' => 'graphql',
'middleware' => [
Nuwave\Lighthouse\Http\Middleware\AcceptJson::class,
Nuwave\Lighthouse\Http\Middleware\AttemptAuthentication::class,
Nuwave\Lighthouse\Http\Middleware\LogGraphQLQueries::class, ], ],

Should route:list also show a websocket route ?

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet

AltStyle によって変換されたページ (->オリジナル) /