[debug_extension] Update sendCommand signature (#2887)

The current Chrome docs only show the Promise-based form of this API, but
a trailing callback parameter is still supported for backwards compatibility.

On success, the callback is invoked with the command's result object. On
failure, it is invoked with *no arguments* and `chrome.runtime.lastError`
is set, so callbacks must accept an optional positional argument.
diff --git a/debug_extension/web/chrome_api.dart b/debug_extension/web/chrome_api.dart
index 27d67ae..d985955 100644
--- a/debug_extension/web/chrome_api.dart
+++ b/debug_extension/web/chrome_api.dart
@@ -55,6 +55,13 @@
 
   external void detach(Debuggee target, Function? callback);
 
+  /// The current Chrome docs only show the Promise-based form of this API, but
+  /// a trailing [callback] is still supported for backwards compatibility.
+  ///
+  /// On success, [callback] is invoked with the command's result object. On
+  /// failure, it is invoked with *no arguments* and `chrome.runtime.lastError`
+  /// is set, so callbacks must accept an optional positional argument (e.g.
+  /// `allowInterop(([result]) {...})`).
   external void sendCommand(
     Debuggee target,
     String method,
diff --git a/debug_extension/web/debug_session.dart b/debug_extension/web/debug_session.dart
index 9011e1f..521db79 100644
--- a/debug_extension/web/debug_session.dart
+++ b/debug_extension/web/debug_session.dart
@@ -234,7 +234,8 @@
     Debuggee(tabId: tabId),
     'Runtime.enable',
     EmptyParam(),
-    allowInterop((_) {
+    // Chrome invokes the callback with no arguments when the command fails.
+    allowInterop(([_]) {
       final chromeError = chrome.runtime.lastError;
       if (chromeError != null) {
         final errorMessage = _translateChromeError(chromeError.message);
@@ -318,13 +319,21 @@
       returnByValue: true,
       contextId: contextId,
     ),
-    allowInterop((dynamic response) {
+    // Chrome invokes the callback with no arguments when the command fails.
+    allowInterop(([Object? response]) {
+      final frameIdentifier = 'Frame at tab $tabId with context $contextId';
+      if (response == null) {
+        final errorMessage =
+            chrome.runtime.lastError?.message ?? 'Unknown error.';
+        debugWarn('Failed to evaluate $frameIdentifier: $errorMessage');
+        completer.complete(false);
+        return;
+      }
       final evalResponse = response as _EvalResponse;
       final value = evalResponse.result.value;
       final appId = value?[0];
       final instanceId = value?[1];
       final dwdsVersion = value?[2];
-      final frameIdentifier = 'Frame at tab $tabId with context $contextId';
       if (appId == null || instanceId == null) {
         debugWarn('$frameIdentifier is not a Dart frame.');
         completer.complete(false);