-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Description
👟 Reproduction steps
Create a Appwrite Collection with some information like:

After that sample document and change document while you are listen to the changes via Realtime. I've changed the example to a singleton like this:
import 'package:appwrite/appwrite.dart';
import 'package:baupro/repositories/models/appwrite_exception_model.dart';
import 'package:baupro/repositories/models/appwrite_response_model.dart';
import 'package:get_it/get_it.dart';
import 'package:talker_flutter/talker_flutter.dart';
class AppwriteRepositorySingleton {
static const String appwriteProjectId = '';
static const String appwriteProjectName = '';
static const String appwritePublicEndpoint = '';
final Client client = Client()
.setProject(appwriteProjectId)
.setEndpoint(appwritePublicEndpoint)
.setLocale('de');
/// Appwrite account instance
late final Account account;
/// Appwrite databases instance
late final Databases databases;
/// Appwrite realtime instance
late final Realtime realtime;
/// Appwrite teams instance
late final Teams teams;
/// Supscription
late RealtimeSubscription realtimeSubscription;
AppwriteRepositorySingleton._internal() {
account = Account(client);
databases = Databases(client);
realtime = Realtime(client);
teams = Teams(client);
realtimeSubscription = realtime.subscribe(['documents']);
_listenToRealtimeEvents();
}
void renewRealtimeSubscription() {
try {
realtimeSubscription.close();
} catch (e, stack) {
_talker.warning(
'Error when closing the old real-time subscription: $e',
e,
stack,
);
}
}
/// Closes the realtime subscription on dispose
void dispose() {
realtimeSubscription.close();
_talker.info('Realtime subscription closed on dispose.');
}
static final AppwriteRepositorySingleton _instance =
AppwriteRepositorySingleton._internal();
/// Singleton instance getter
factory AppwriteRepositorySingleton() => _instance;
/////////////////////////////////////
// Realtime events
/////////////////////////////////////
/// Timeout for reconnecting to Realtime
int get _reconnectTimeout => 5;
/// Listens to realtime events and handles errors.
void _listenToRealtimeEvents() {
realtimeSubscription.stream.listen(
(data) {
_talker.debug('Realtime event: ${data.payload}');
},
onError: (error, stackTrace) {
_talker.error('Realtime error: $error', error, stackTrace);
Future.delayed(Duration(seconds: _reconnectTimeout), () {
_talker.info('Attempting to resubscribe to Realtime...');
realtimeSubscription.close();
realtimeSubscription = realtime.subscribe(['documents']);
_listenToRealtimeEvents();
});
},
onDone: () {
_talker.info(
'Realtime subscription closed. Attempting to resubscribe...',
);
Future.delayed(Duration(seconds: 1), () {
realtimeSubscription = realtime.subscribe(['documents']);
_listenToRealtimeEvents();
});
},
cancelOnError: false,
);
}
/////////////////////////////////////
// Logging section
/////////////////////////////////////
/// Get the talker instance
Talker get _talker => GetIt.instance.get<Talker>();
/// Handles exceptions and displays an error notification.
void handleAppwriteException(
Object e,
StackTrace? stackTrace, {
String? messagePrefix,
}) {
final prefix = messagePrefix != null ? '$messagePrefix: ' : '';
if (e is AppwriteException) {
_talker.error(
'${prefix}AppwriteException caught in AppwriteRepository: ${e.message} (Code: ${e.code}, Type: ${e.type})',
e,
stackTrace,
);
} else {
_talker.error(
'${prefix}Exception caught in AppwriteRepository',
e,
stackTrace,
);
}
// TODO: Füge hier ggf. weitere Fehlerbehandlung hinzu (z.B. Benachrichtigungen)
}
/// Wraps an Appwrite request in a try-catch block and logs the result.
Future<AppwriteResponseModel<T>> safeAppwriteRequest<T>(
Future<T> Function() requestFunction, {
String? operationName,
}) async {
final opName = operationName ?? 'Appwrite Operation';
try {
_talker.info('$opName started.');
final result = await requestFunction();
_talker.info('$opName successful.');
return AppwriteResponseModel(response: result, exception: null);
} catch (e, stack) {
handleAppwriteException(e, stack, messagePrefix: '$opName failed');
return AppwriteResponseModel(
response: null,
exception: AppwriteExceptionModel(
message: e is AppwriteException ? e.message : e.toString(),
code: e is AppwriteException ? e.code : null,
type: e is AppwriteException ? e.type : null,
),
);
}
}
/////////////////////////////////////
// Get Methods
/////////////////////////////////////
/// Pings the Appwrite server and captures the response.
Future<AppwriteResponseModel<bool>> checkConnection() async =>
await safeAppwriteRequest(() async {
final response = await client.ping();
return response.isNotEmpty;
}, operationName: 'Check Connection');
}
👍 Expected behavior
I should get the information on a change cause of the talker log _talker.debug('Realtime event: ${data.payload}');
.
👎 Actual Behavior
Just if I set the collection permission to Any => Read I got this information:

flutter: │ [debug] | 16:37:12 394ms | Realtime event: {Firstname: XXX, Lastname: XXX, Position: XXX, Email: XXX, Active: true, StartWork: null, EndWork: null, BreakTime: null, $id: 68a6f98241f21b4b68d4, $createdAt: 2025-08-21T10:48:25.949+00:00, $updatedAt: 2025-08-21T14:37:03.903+00:00, $permissions: [read("team:68a5837e0027b2a5151e"), update("team:68a5837e0027b2a5151e"), delete("team:68a5837e0027b2a5151e")], Company: {Name: First-Coder, Active: true, TeamId: 68a5837e0027b2a5151e, $id: 68a582570010bb3402be, $createdAt: 2025-08-20T08:07:43.063+00:00, $updatedAt: 2025-08-20T11:14:57.254+00:00, $permissions: [read("team:68a5837e0027b2a5151e"), update("team:68a5837e0027b2a5151e")], Address: {Street: Teststreifen, HouseNumber: 12345, ZipCode: 12345, City: Berlin, Country: Deutschland, $id: 688874740032810f50f9, $createdAt: 2025-07-29T07:12:47.357+00:00, $updatedAt: 2025-07-29T07:12:47.357+00:00, $permissions: [], $databaseId: 687e537b00041c7db62a, $collectionId: 688872a600297a5ac6ba}, $databaseId: 687e537b00041c7db62a, $collectionId: 68a4b21a0005c851c6c3}, $databaseId: 687e537b00041c7db62a, $collectionId: 688871f40011c1886efe}
When I just have the team permissions active I don´t get any realtime messages. But the account is part of the team. I've also have tried to renew the subscription after login like in the sample above without success.
🎲 Appwrite version
Different version (specify in environment)
💻 Operating system
Linux
🧱 Your Environment
Appwrite version: 1.7.4
Flutter version: appwrite: ^16.1.0
Development on macOS
👀 Have you spent some time to check if this issue has been raised before?
- I checked and didn't find similar issue
I am not sure if the issue 🐛 Bug Report: Realtime only emits events with guest / any read permissions #10353 is similar
I am not sure if the issue #8925
🏢 Have you read the Code of Conduct?
- I have read the Code of Conduct