Browse Source

Improve error message for missing reflection data (#2038)

Motivation:

The message for missing reflection data isn't very helpful as it doesn't
indicate what reflection data is missing.

Modifications:

- Improve the error message
- Add note about well-known-types

Result:

Clearer error message
George Barnett 1 year ago
parent
commit
d13926b022

+ 12 - 6
Sources/GRPCReflectionService/Server/ReflectionService.swift

@@ -40,6 +40,8 @@ public final class ReflectionService: CallHandlerProvider, Sendable {
   /// - Parameter fileURLs: The URLs of the files containing serialized reflection data.
   /// - Parameter version: The version of the reflection service to create.
   ///
+  /// - Note: Reflection data for well-known-types must be provided if any of your reflection data depends
+  ///   on them.
   /// - Throws: When a file can't be read from disk or parsed.
   public convenience init(reflectionDataFileURLs fileURLs: [URL], version: Version) throws {
     let filePaths: [String]
@@ -64,6 +66,8 @@ public final class ReflectionService: CallHandlerProvider, Sendable {
   /// - Parameter filePaths: The paths to files containing serialized reflection data.
   /// - Parameter version: The version of the reflection service to create.
   ///
+  /// - Note: Reflection data for well-known-types must be provided if any of your reflection data depends
+  ///   on them.
   /// - Throws: When a file can't be read from disk or parsed.
   public init(reflectionDataFilePaths filePaths: [String], version: Version) throws {
     let fileDescriptorProtos = try ReflectionService.readSerializedFileDescriptorProtos(
@@ -218,12 +222,14 @@ internal struct ReflectionServiceData: Sendable {
         let serializedFileDescriptorProto = protoData.serializedFileDescriptorProto
         serializedFileDescriptorProtos.append(serializedFileDescriptorProto)
       } else {
-        return .failure(
-          GRPCStatus(
-            code: .notFound,
-            message: "The provided file or a dependency of the provided file could not be found."
-          )
-        )
+        let base = "No reflection data for '\(currentFileName)'"
+        let message: String
+        if fileName == currentFileName {
+          message = base + "."
+        } else {
+          message = base + " which is a dependency of '\(fileName)'."
+        }
+        return .failure(GRPCStatus(code: .notFound, message: message))
       }
       visited.insert(currentFileName)
     }

+ 1 - 1
Tests/GRPCTests/GRPCReflectionServiceTests/ReflectionServiceIntegrationTests.swift

@@ -287,7 +287,7 @@ final class ReflectionServiceIntegrationTests: GRPCTestCase {
       XCTAssertEqual(message.errorResponse.errorCode, Int32(GRPCStatus.Code.notFound.rawValue))
       XCTAssertEqual(
         message.errorResponse.errorMessage,
-        "The provided file or a dependency of the provided file could not be found."
+        "No reflection data for 'invalidFileName.proto'."
       )
     }
   }

+ 3 - 2
Tests/GRPCTests/GRPCReflectionServiceTests/ReflectionServiceUnitTests.swift

@@ -349,7 +349,7 @@ final class ReflectionServiceUnitTests: GRPCTestCase {
         status,
         GRPCStatus(
           code: .notFound,
-          message: "The provided file or a dependency of the provided file could not be found."
+          message: "No reflection data for 'invalid.proto'."
         )
       )
     }
@@ -368,7 +368,8 @@ final class ReflectionServiceUnitTests: GRPCTestCase {
         status,
         GRPCStatus(
           code: .notFound,
-          message: "The provided file or a dependency of the provided file could not be found."
+          message:
+            "No reflection data for 'invalidDependency' which is a dependency of 'bar1.proto'."
         )
       )
     }