@@ -63,7 +63,8 @@ class StreamingSyncImplementation {
6363 await streamingSyncIteration ();
6464 // Continue immediately
6565 } catch (e, stacktrace) {
66- log.warning ('Sync error' , e, stacktrace);
66+ final message = _syncErrorMessage (e);
67+ log.warning ('Sync error: $message ' , e, stacktrace);
6768 invalidCredentials = true ;
6869
6970 _updateStatus (
@@ -124,7 +125,7 @@ class StreamingSyncImplementation {
124125 Future <String > getWriteCheckpoint () async {
125126 final credentials = await credentialsCallback ();
126127 if (credentials == null ) {
127- throw AssertionError ("Not logged in" );
128+ throw CredentialsException ("Not logged in" );
128129 }
129130 final uri = credentials.endpointUri ('write-checkpoint2.json' );
130131
@@ -139,7 +140,7 @@ class StreamingSyncImplementation {
139140 }
140141 }
141142 if (response.statusCode != 200 ) {
142- throw getError (response);
143+ throw _getError (response);
143144 }
144145
145146 final body = convert.jsonDecode (response.body);
@@ -237,7 +238,8 @@ class StreamingSyncImplementation {
237238 } else if (line is StreamingSyncCheckpointDiff ) {
238239 // TODO: It may be faster to just keep track of the diff, instead of the entire checkpoint
239240 if (targetCheckpoint == null ) {
240- throw AssertionError ('Checkpoint diff without previous checkpoint' );
241+ throw PowerSyncProtocolException (
242+ 'Checkpoint diff without previous checkpoint' );
241243 }
242244 final diff = line;
243245 final Map <String , BucketChecksum > newBuckets = {};
@@ -322,7 +324,7 @@ class StreamingSyncImplementation {
322324 Stream <Object ?> streamingSyncRequest (StreamingSyncRequest data) async * {
323325 final credentials = await credentialsCallback ();
324326 if (credentials == null ) {
325- throw AssertionError ('Not logged in' );
327+ throw CredentialsException ('Not logged in' );
326328 }
327329 final uri = credentials.endpointUri ('sync/stream' );
328330
@@ -339,7 +341,7 @@ class StreamingSyncImplementation {
339341 }
340342 }
341343 if (res.statusCode != 200 ) {
342- throw await getStreamedError (res);
344+ throw await _getStreamedError (res);
343345 }
344346
345347 // Note: The response stream is automatically closed when this loop errors
@@ -349,33 +351,38 @@ class StreamingSyncImplementation {
349351 }
350352}
351353
352- HttpException getError (http.Response response) {
354+ SyncResponseException _getError (http.Response response) {
353355 try {
354356 final body = response.body;
355357 final decoded = convert.jsonDecode (body);
356- final details = stringOrFirst (decoded['error' ]? ['details' ]) ?? body;
358+ final details = _stringOrFirst (decoded['error' ]? ['details' ]) ?? body;
357359 final message = '${response .reasonPhrase ?? "Request failed" }: $details ' ;
358- return HttpException (message, uri : response.request ? .url );
360+ return SyncResponseException ( response.statusCode, message );
359361 } on Error catch (_) {
360- return HttpException (response.reasonPhrase ?? "Request failed" ,
361- uri: response.request? .url);
362+ return SyncResponseException (
363+ response.statusCode,
364+ response.reasonPhrase ?? "Request failed" ,
365+ );
362366 }
363367}
364368
365- Future <HttpException > getStreamedError (http.StreamedResponse response) async {
369+ Future <SyncResponseException > _getStreamedError (
370+ http.StreamedResponse response) async {
366371 try {
367372 final body = await response.stream.bytesToString ();
368373 final decoded = convert.jsonDecode (body);
369- final details = stringOrFirst (decoded['error' ]? ['details' ]) ?? body;
374+ final details = _stringOrFirst (decoded['error' ]? ['details' ]) ?? body;
370375 final message = '${response .reasonPhrase ?? "Request failed" }: $details ' ;
371- return HttpException (message, uri : response.request ? .url );
376+ return SyncResponseException ( response.statusCode, message );
372377 } on Error catch (_) {
373- return HttpException (response.reasonPhrase ?? "Request failed" ,
374- uri: response.request? .url);
378+ return SyncResponseException (
379+ response.statusCode,
380+ response.reasonPhrase ?? "Request failed" ,
381+ );
375382 }
376383}
377384
378- String ? stringOrFirst (Object ? details) {
385+ String ? _stringOrFirst (Object ? details) {
379386 if (details == null ) {
380387 return null ;
381388 } else if (details is String ) {
@@ -386,3 +393,63 @@ String? stringOrFirst(Object? details) {
386393 return null ;
387394 }
388395}
396+
397+ /// Attempt to give a basic summary of the error for cases where the full error
398+ /// is not logged.
399+ String _syncErrorMessage (Object ? error) {
400+ if (error == null ) {
401+ return 'Unknown' ;
402+ } else if (error is HttpException ) {
403+ return 'Sync service error' ;
404+ } else if (error is SyncResponseException ) {
405+ if (error.statusCode == 401 ) {
406+ return 'Authorization error' ;
407+ } else {
408+ return 'Sync service error' ;
409+ }
410+ } else if (error is SocketException ) {
411+ return 'Connection error' ;
412+ } else if (error is ArgumentError || error is FormatException ) {
413+ return 'Configuration error' ;
414+ } else if (error is CredentialsException ) {
415+ return 'Credentials error' ;
416+ } else if (error is PowerSyncProtocolException ) {
417+ return 'Protocol error' ;
418+ } else {
419+ return '${error .runtimeType }' ;
420+ }
421+ }
422+
423+ class CredentialsException implements Exception {
424+ String message;
425+
426+ CredentialsException (this .message);
427+
428+ @override
429+ toString () {
430+ return 'CredentialsException: $message ' ;
431+ }
432+ }
433+
434+ class PowerSyncProtocolException implements Exception {
435+ String message;
436+
437+ PowerSyncProtocolException (this .message);
438+
439+ @override
440+ toString () {
441+ return 'SyncProtocolException: $message ' ;
442+ }
443+ }
444+
445+ class SyncResponseException implements Exception {
446+ int statusCode;
447+ String description;
448+
449+ SyncResponseException (this .statusCode, this .description);
450+
451+ @override
452+ toString () {
453+ return 'SyncResponseException: $statusCode $description ' ;
454+ }
455+ }
0 commit comments