Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Device Client] MQTT error reconnecting #268

Closed
pizerg opened this issue Jul 2, 2018 · 9 comments
Closed

[Device Client] MQTT error reconnecting #268

pizerg opened this issue Jul 2, 2018 · 9 comments
Labels
bug fix checked in Fix checked into main or preview, but not yet released.

Comments

@pizerg
Copy link

pizerg commented Jul 2, 2018

  • OS and version used: Raspbian Jessie and Windows 10

  • Java runtime used: JDK 1.8 (Oracle's)

  • SDK version used: 1.11.2

Description of the issue:

Around 2 minuts after a connection drop, a socket timeout is wrongly identified as non-retryable BAD_CREDENTIALS exception and the reconnection process stops (we have it configured to keep trying to reconnect 'forever' as operation timeout is set to Long.MAX_VALUE) making us having to restart all affected devices. Haven't tried with the latest version of the sdk because the release notes do not state any change or bugfix, only new features.

Despite this being a bug with exceptions classification, it'd be nice to have an option or configuration for the sdk to keep trying to reconnect indefinitely (recreating any needed objects/connections in case a critical exception happens)

Code sample exhibiting the issue:

DeviceClient client = new DeviceClient(CS_HERE, IotHubClientProtocol.MQTT);
client.setOperationTimeout(Long.MAX_VALUE);
client.registerConnectionStatusChangeCallback(CALLBACK_CODE_HERE)
client.open()
....
wait for a connection drop
....

Console log of the issue:

The first message on the connection callback status are correctly identified as NO_NETWORK:

2018-07-01 09:04:43,841 AzureIoTHub [MQTT Rec: SOME_ID] DEBUG: IoTHub connection state callback, status: DISCONNECTED_RETRYING reason: NO_NETWORK
2018-07-01 09:04:43,841 AzureIoTHub [MQTT Rec: SOME_ID] DEBUG: IoTHub connection state callback error
com.microsoft.azure.sdk.iot.device.exceptions.ProtocolException: Mqtt connection lost
	at com.microsoft.azure.sdk.iot.device.transport.mqtt.exceptions.PahoExceptionTranslator.convertToMqttException(PahoExceptionTranslator.java:69)
	at com.microsoft.azure.sdk.iot.device.transport.mqtt.Mqtt.connectionLost(Mqtt.java:332)
	at org.eclipse.paho.client.mqttv3.internal.CommsCallback.connectionLost(CommsCallback.java:292)
	at org.eclipse.paho.client.mqttv3.internal.ClientComms.shutdownConnection(ClientComms.java:423)
	at org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run(CommsReceiver.java:181)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
Caused by: Connection lost (32109) - java.io.EOFException
	... 8 more
Caused by: java.io.EOFException
	at java.io.DataInputStream.readByte(DataInputStream.java:267)
	at org.eclipse.paho.client.mqttv3.internal.wire.MqttInputStream.readMqttWireMessage(MqttInputStream.java:92)
	at org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run(CommsReceiver.java:133)
	... 7 more

Two minutes later a timeout is detected as BAD_CREDENTIALS which the code treats as "non retryable" exception.

2018-07-01 09:06:04,726 AzureIoTHub [MQTT Rec: SOME_ID] DEBUG: IoTHub connection state callback, status: DISCONNECTED reason: BAD_CREDENTIAL
2018-07-01 09:06:04,727 AzureIoTHub [MQTT Rec: SOME_ID] DEBUG: IoTHub connection state callback error
com.microsoft.azure.sdk.iot.device.exceptions.ProtocolException: Unable to establish MQTT connection
	at com.microsoft.azure.sdk.iot.device.transport.mqtt.exceptions.PahoExceptionTranslator.convertToMqttException(PahoExceptionTranslator.java:41)
	at com.microsoft.azure.sdk.iot.device.transport.mqtt.Mqtt.connect(Mqtt.java:105)
	at com.microsoft.azure.sdk.iot.device.transport.mqtt.MqttMessaging.start(MqttMessaging.java:40)
	at com.microsoft.azure.sdk.iot.device.transport.mqtt.MqttIotHubConnection.open(MqttIotHubConnection.java:181)
	at com.microsoft.azure.sdk.iot.device.transport.IotHubTransport.openConnection(IotHubTransport.java:642)
	at com.microsoft.azure.sdk.iot.device.transport.IotHubTransport.singleReconnectAttempt(IotHubTransport.java:760)
	at com.microsoft.azure.sdk.iot.device.transport.IotHubTransport.reconnect(IotHubTransport.java:714)
	at com.microsoft.azure.sdk.iot.device.transport.IotHubTransport.handleDisconnection(IotHubTransport.java:672)
	at com.microsoft.azure.sdk.iot.device.transport.IotHubTransport.onConnectionLost(IotHubTransport.java:205)
	at com.microsoft.azure.sdk.iot.device.transport.mqtt.Mqtt.connectionLost(Mqtt.java:340)
	at org.eclipse.paho.client.mqttv3.internal.CommsCallback.connectionLost(CommsCallback.java:292)
	at org.eclipse.paho.client.mqttv3.internal.ClientComms.shutdownConnection(ClientComms.java:423)
	at org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run(CommsReceiver.java:181)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
Caused by: MqttException (0) - java.net.SocketTimeoutException: connect timed out
	at org.eclipse.paho.client.mqttv3.internal.ExceptionHelper.createMqttException(ExceptionHelper.java:38)
	at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:715)
	... 7 more
Caused by: java.net.SocketTimeoutException: connect timed out
	at java.net.PlainSocketImpl.socketConnect(Native Method)
	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
	at java.net.Socket.connect(Socket.java:589)
	at org.eclipse.paho.client.mqttv3.internal.TCPNetworkModule.start(TCPNetworkModule.java:80)
	at org.eclipse.paho.client.mqttv3.internal.SSLNetworkModule.start(SSLNetworkModule.java:103)
	at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:701)
	... 7 more
@jasmineymlo
Copy link
Contributor

Thanks for filing the issue. We will look into the classification of exception in this case and fix accordingly. For configuring the sdk to reconnect indefinitely, setting the operation timeout to max value is the way to go.

If you are referring retrying indefinitely in case of "non-retryable" exception, it could be achieved on the application side. You could implement connection status change callback and handle the disconnect accordingly, e.g.:

DeviceClient client = new DeviceClient("", IotHubClientProtocol.AMQPS, publicKeyCertificateString, false, privateKeyString, false);

client.registerConnectionStatusChangeCallback(new IotHubConnectionStatusChangeCallback()
{
@OverRide
public void execute(IotHubConnectionStatus status, IotHubConnectionStatusChangeReason statusChangeReason, Throwable throwable, Object callbackContext) {
System.out.println();
System.out.println("CONNECTION STATUS UPDATE: " + status);
System.out.println("CONNECTION STATUS REASON: " + statusChangeReason);
System.out.println("CONNECTION STATUS THROWABLE: " + (throwable == null ? "null" : throwable.getMessage()));
System.out.println();

    if (status == IotHubConnectionStatus.DISCONNECTED)
    {
        //connection was lost, and is not being re-established. Look at provided exception for 
        // how to resolve this issue. Cannot send messages until this issue is resolved, and you manually
        // re-open the device client
    }
    else if (status == IotHubConnectionStatus.DISCONNECTED_RETRYING)
    {
        //connection was lost, but is being re-established. Can still send messages, but they won't
        // be sent until the connection is re-established
    }
    else if (status == IotHubConnectionStatus.CONNECTED)
    {
        //Connection was successfully re-established. Can send messages.
    }
}

}, new Object());

Please note that it is not recommended to just reopen indefinitely without evaluating the underlying exception, since it could waste resources if the system is already suggesting that the situation is non-recoverable.

@pizerg
Copy link
Author

pizerg commented Jul 3, 2018

Thanks, I already had something similar to handle DISCONNECTED case, just thought that a timeout shouldn't be considered non-retryable.

@timtay-microsoft
Copy link
Member

We are going to go ahead and alter the SDK to interpret SocketTimeoutException as a retryable exception in the future. We'll keep this thread updated as we merge in those changes and eventually release them

@jasmineymlo
Copy link
Contributor

0a21df8 fixed the mapping of SocketTimeoutException. It will be included in the next release. Thanks.

@jasmineymlo jasmineymlo added the fix checked in Fix checked into main or preview, but not yet released. label Jul 17, 2018
@pizerg
Copy link
Author

pizerg commented Jul 27, 2018

Thanks for the fix! Do you have an estimated release date for the new version?

@timtay-microsoft
Copy link
Member

We should be releasing in the next few days. I'll update this thread as soon as we do.

@jasmineymlo
Copy link
Contributor

@youmingzeng
Copy link

I can't use the new version 1.13.2 in android. (android API level : 19)。Only dependency this SDK。
At first,errMsg was

> Annotation processors must be explicitly declared now.  The following dependencies on the compile classpath are found to contain annotation processor.  Please add them to the annotationProcessor configuration.
    - log4j-core-2.11.0.jar (org.apache.logging.log4j:log4j-core:2.11.0)
  Alternatively, set android.defaultConfig.javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true to continue with previous behavior.  Note that this option is deprecated and will be removed in the future.
  See https://developer.android.com/r/tools/annotation-processor-error-message.html for more details.

after I add this StatementjavaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true,errMsg became

Caused by: com.android.tools.r8.utils.AbortException: Error: MethodHandle.invoke and MethodHandle.invokeExact are only supported starting with Android O (--min-api 26)
	at com.android.tools.r8.utils.Reporter.failIfPendingErrors(Reporter.java:116)
	at com.android.tools.r8.utils.Reporter.fatalError(Reporter.java:74)
	at com.android.tools.r8.utils.ExceptionUtils.withCompilationHandler(ExceptionUtils.java:59)
	... 10 more

so I included the following within build.gradle

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

still fail:

error processing C:\Users\YMZ\.gradle\caches\modules-2\files-2.1\org.apache.logging.log4j\log4j-api\2.11.0\bede79a3f150711634a3047985517431bf6499f2\log4j-api-2.11.0.jar
java.lang.RuntimeException
	at org.objectweb.asm.ClassVisitor.visitModule(ClassVisitor.java:148)
	at org.objectweb.asm.ClassReader.readModule(ClassReader.java:731)
	at org.objectweb.asm.ClassReader.accept(ClassReader.java:632)
	at org.objectweb.asm.ClassReader.accept(ClassReader.java:500)
	at com.android.builder.desugaring.DesugaringClassAnalyzer.analyze(DesugaringClassAnalyzer.java:144)
	at com.android.builder.desugaring.DesugaringClassAnalyzer.analyzeJar(DesugaringClassAnalyzer.java:92)
	at com.android.builder.desugaring.DesugaringClassAnalyzer.analyze(DesugaringClassAnalyzer.java:63)
	at com.android.build.gradle.internal.transforms.DesugarIncrementalTransformHelper.lambda$getInitalGraphData$4(DesugarIncrementalTransformHelper.java:150)
	at java.util.concurrent.ForkJoinTask$AdaptedCallable.exec(ForkJoinTask.java:1424)
	at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
	at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
	at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
	at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
java.lang.RuntimeException: java.lang.RuntimeException
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:593)
	at java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:677)
	at java.util.concurrent.ForkJoinTask.join(ForkJoinTask.java:720)
	at com.android.ide.common.internal.WaitableExecutor.waitForTasksWithQuickFail(WaitableExecutor.java:146)
	at com.android.build.gradle.internal.transforms.DesugarIncrementalTransformHelper.getInitalGraphData(DesugarIncrementalTransformHelper.java:162)
	at com.android.build.gradle.internal.transforms.DesugarIncrementalTransformHelper.makeDesugaringGraph(DesugarIncrementalTransformHelper.java:130)
	at com.google.common.base.Suppliers$NonSerializableMemoizingSupplier.get(Suppliers.java:160)
	at com.android.build.gradle.internal.transforms.DesugarIncrementalTransformHelper.getDependenciesPaths(DesugarIncrementalTransformHelper.java:231)
	at com.android.build.gradle.internal.transforms.DexArchiveBuilderTransform.getD8DesugaringCacheInfo(DexArchiveBuilderTransform.java:461)
	at com.android.build.gradle.internal.transforms.DexArchiveBuilderTransform.transform(DexArchiveBuilderTransform.java:375)
	at com.android.build.gradle.internal.pipeline.TransformTask$2.call(TransformTask.java:239)
	at com.android.build.gradle.internal.pipeline.TransformTask$2.call(TransformTask.java:235)
	at com.android.builder.profile.ThreadRecorder.record(ThreadRecorder.java:102)
	at com.android.build.gradle.internal.pipeline.TransformTask.transform(TransformTask.java:230)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
	at org.gradle.api.internal.project.taskfactory.IncrementalTaskAction.doExecute(IncrementalTaskAction.java:50)
	at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:39)
	at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:26)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$1.run(ExecuteActionsTaskExecuter.java:124)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:113)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:95)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:73)
	at org.gradle.api.internal.tasks.execution.OutputDirectoryCreatingTaskExecuter.execute(OutputDirectoryCreatingTaskExecuter.java:51)
	at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:59)
	at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54)
	at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:59)
	at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:101)
	at org.gradle.api.internal.tasks.execution.FinalizeInputFilePropertiesTaskExecuter.execute(FinalizeInputFilePropertiesTaskExecuter.java:44)
	at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:91)
	at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:62)
	at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:59)
	at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
	at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
	at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
	at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.run(DefaultTaskGraphExecuter.java:256)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
	at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:249)
	at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:238)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.processTask(DefaultTaskPlanExecutor.java:123)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.access$200(DefaultTaskPlanExecutor.java:79)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:104)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:98)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.execute(DefaultTaskExecutionPlan.java:663)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.executeWithTask(DefaultTaskExecutionPlan.java:597)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.run(DefaultTaskPlanExecutor.java:98)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.RuntimeException
	at org.objectweb.asm.ClassVisitor.visitModule(ClassVisitor.java:148)
	at org.objectweb.asm.ClassReader.readModule(ClassReader.java:731)
	at org.objectweb.asm.ClassReader.accept(ClassReader.java:632)
	at org.objectweb.asm.ClassReader.accept(ClassReader.java:500)
	at com.android.builder.desugaring.DesugaringClassAnalyzer.analyze(DesugaringClassAnalyzer.java:144)
	at com.android.builder.desugaring.DesugaringClassAnalyzer.analyzeJar(DesugaringClassAnalyzer.java:92)
	at com.android.builder.desugaring.DesugaringClassAnalyzer.analyze(DesugaringClassAnalyzer.java:63)
	at com.android.build.gradle.internal.transforms.DesugarIncrementalTransformHelper.lambda$getInitalGraphData$4(DesugarIncrementalTransformHelper.java:150)
	at java.util.concurrent.ForkJoinTask$AdaptedCallable.exec(ForkJoinTask.java:1424)
	at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
	at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
	at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
	at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)

:app:transformClassesWithDexBuilderForDebug FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:transformClassesWithDexBuilderForDebug'.
> com.android.build.api.transform.TransformException: java.lang.RuntimeException: java.lang.RuntimeException

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 5s

Why log4j-api-2.11.0.jar process fail in android?

@jasmineymlo
Copy link
Contributor

@YMZ1994420 I have open a new issue to track #313

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug fix checked in Fix checked into main or preview, but not yet released.
Projects
None yet
Development

No branches or pull requests

4 participants