google / android-fhir

The Android FHIR SDK is a set of Kotlin libraries for building offline-capable, mobile-first healthcare applications using the HL7® FHIR® standard on Android.
https://google.github.io/android-fhir/
Apache License 2.0
495 stars 296 forks source link

App crash when form loaded in edit mode contains unanswered repeat group item #2685

Open Rkareko opened 1 month ago

Rkareko commented 1 month ago

Describe the bug When a form containing a repeat group is saved without populating the items withing the repeat group, opening the form in edit mode results in an app crash.

The following exception is thrown: -

AndroidRuntime          com.google.android.fhir.demo         E  FATAL EXCEPTION: main
                                                                                                    Process: com.google.android.fhir.demo, PID: 4641
                                                                                                    java.lang.IllegalArgumentException: Failed requirement.
                                                                                                        at com.google.android.fhir.datacapture.extensions.MoreQuestionnairesKt.forEachItemPair(MoreQuestionnaires.kt:202)
                                                                                                        at com.google.android.fhir.datacapture.extensions.MoreQuestionnairesKt.forEachItemPair(MoreQuestionnaires.kt:226)
                                                                                                        at com.google.android.fhir.datacapture.extensions.MoreQuestionnairesKt.forEachItemPair(MoreQuestionnaires.kt:217)
                                                                                                        at com.google.android.fhir.datacapture.extensions.MoreQuestionnairesKt.forEachItemPair(MoreQuestionnaires.kt:190)
                                                                                                        at com.google.android.fhir.datacapture.QuestionnaireViewModel.initializeCalculatedExpressions(QuestionnaireViewModel.kt:612)
                                                                                                        at com.google.android.fhir.datacapture.QuestionnaireViewModel.access$initializeCalculatedExpressions(QuestionnaireViewModel.kt:85)
                                                                                                        at com.google.android.fhir.datacapture.QuestionnaireViewModel$questionnaireStateFlow$2.invokeSuspend(QuestionnaireViewModel.kt:593)
                                                                                                        at com.google.android.fhir.datacapture.QuestionnaireViewModel$questionnaireStateFlow$2.invoke(Unknown Source:8)
                                                                                                        at com.google.android.fhir.datacapture.QuestionnaireViewModel$questionnaireStateFlow$2.invoke(Unknown Source:4)
                                                                                                        at kotlinx.coroutines.flow.FlowKt__TransformKt$onEach$$inlined$unsafeTransform$1$2.emit(Emitters.kt:219)
                                                                                                        at kotlinx.coroutines.flow.FlowKt__TransformKt$withIndex$1$1.emit(Transform.kt:67)
                                                                                                        at kotlinx.coroutines.flow.FlowKt__ZipKt$combine$$inlined$combineUnsafe$FlowKt__ZipKt$1$2.invokeSuspend(Zip.kt:258)
                                                                                                        at kotlinx.coroutines.flow.FlowKt__ZipKt$combine$$inlined$combineUnsafe$FlowKt__ZipKt$1$2.invoke(Unknown Source:13)
                                                                                                        at kotlinx.coroutines.flow.FlowKt__ZipKt$combine$$inlined$combineUnsafe$FlowKt__ZipKt$1$2.invoke(Unknown Source:6)
                                                                                                        at kotlinx.coroutines.flow.internal.CombineKt$combineInternal$2.invokeSuspend(Combine.kt:73)
                                                                                                        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
                                                                                                        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
                                                                                                        at kotlinx.coroutines.EventLoop.processUnconfinedEvent(EventLoop.common.kt:65)
                                                                                                        at kotlinx.coroutines.DispatchedTaskKt.resumeUnconfined(DispatchedTask.kt:241)
                                                                                                        at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:159)
                                                                                                        at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:466)
                                                                                                        at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:500)
                                                                                                        at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:489)
                                                                                                        at kotlinx.coroutines.CancellableContinuationImpl.resumeWith(CancellableContinuationImpl.kt:364)
                                                                                                        at kotlinx.coroutines.flow.SharedFlowImpl.tryEmit(SharedFlow.kt:409)
                                                                                                        at kotlinx.coroutines.flow.internal.SubscriptionCountStateFlow.increment(AbstractSharedFlow.kt:125)
                                                                                                        at kotlinx.coroutines.flow.internal.AbstractSharedFlow.allocateSlot(AbstractSharedFlow.kt:64)
                                                                                                        at kotlinx.coroutines.flow.StateFlowImpl.collect(StateFlow.kt:382)
                                                                                                        at kotlinx.coroutines.flow.ReadonlyStateFlow.collect(Unknown Source:2)
                                                                                                        at com.google.android.fhir.datacapture.QuestionnaireFragment$onViewCreated$3.invokeSuspend(QuestionnaireFragment.kt:158)
                                                                                                        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
                                                                                                        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
                                                                                                        at androidx.lifecycle.DispatchQueue.drainQueue(DispatchQueue.kt:74)
                                                                                                        at androidx.lifecycle.DispatchQueue.resume(DispatchQueue.kt:53)
                                                                                                        at androidx.lifecycle.LifecycleController.observer$lambda$0(LifecycleController.kt:40)
                                                                                                        at androidx.lifecycle.LifecycleController.$r8$lambda$oWRpCg8vH8nSBgktHTqCr-ANl8M(Unknown Source:0)
                                                                                                        at androidx.lifecycle.LifecycleController$$ExternalSyntheticLambda0.onStateChanged(D8$$SyntheticClass:0)
                                                                                                        at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.kt:314)
                                                                                                        at androidx.lifecycle.LifecycleRegistry.forwardPass(LifecycleRegistry.kt:251)
                                                                                                        at androidx.lifecycle.LifecycleRegistry.sync(LifecycleRegistry.kt:287)

Component SDC library

To Reproduce Steps to reproduce the behavior:

  1. On the demo app new patient registration form, change the Client info group into a repeat group by adding "repeats": "true". The Client info repeat group contains the first and family name fields.
  2. Run the demo app and register a new patient. Do not click on the +Add button under the Client info title i.e do not add the first or family name.
  3. Fill in the rest of the fields and save the form
  4. Go to the patient list and open the card for the patient
  5. Click on the edit symbol that appears on the top right section of the screen.
  6. App crashes

Expected behavior App should not crash when the form is opened in edit mode.

Screenshots If applicable, add screenshots to help explain your problem. Add patient form with the Client Info as a repeat group item

add_patient-With_client_info_as_a_repeat_group

Smartphone (please complete the following information):

Additional context It seems that the addMissingResponseItems function that is called in the QuestionnaireViewModel.init function does not handle repeat groups.

Would you like to work on the issue? Please state if this issue should be assigned to you or who you think could help to solve this issue.