1. Create new instrumentation schema and stream for app errors
2. Log HCaptcha errors.
###Proposed structure:
**Schema name:** app_error (e.g. "/analytics/mobile_apps/app_error/1.0.0")
**Stream name:** app_error
####Captured values
**domain:** //String//
Error type / namespace. This would include the name of our custom errors (like `WMFData.WMFCoreDataStoreError`) or a generic system error type (like `NSURLErrorDomain`)
**code:** //String//
Specific error case. In our case this could be another custom error name (like `setupMissingDataModelFileURL`) or a generic system error code (like `-1000`)
**category**: //String, optional//
An additional way of categorizing errors should we choose. We could use it to describe the layer it happened in (UI, Networking stack, something else), or use it to describe urgency (High, Medium, etc).
**details**: //comma-delimited String, optional//
Catch-all for any other information we want to grab. I'm thinking of treating this like we do action_data in the app_interaction schema. We can add a call stack in here, or any additional detail we want.
####Examples
Here are some payload examples from tinkering around.
**Forced error in WMFComponents package when deleting article tabs**
```
{
"code": "coreDataStoreUnavailable",
"details": "stack_trace:3 Wikipedia.debug.dylib 0x00000001041b6558 $s9Wikipedia23TabsOverviewCoordinatorC8logErroryys0F0_pF + 276 | 4 Wikipedia.debug.dylib 0x00000001041b6c24 $s9Wikipedia23TabsOverviewCoordinatorC13WMFComponents010WMFArticleB15LoggingDelegateAadEP8logErroryys0J0_pFTW + 12 | 5 WMF 0x0000000107c73f88 $s13WMFComponents23WMFArticleTabsViewModelC014didTapCloseAllC0yyFyyYacfU_TY3_ + 60",
"dt": "2026-02-10T23:32:20Z",
"is_temp": false,
"meta": {
"id": "0DC5C320-E417-4450-962B-5F28FE666AEE",
"stream": "app_error"
},
"is_anon": true,
"app_session_id": "f57f8aacc7f51070544e",
"$schema": "/analytics/mobile_apps/app_error/1.0.0",
"category": "WMFComponents",
"platform": "ios",
"domain": "WMFData.WMFDataControllerError",
"primary_language": "test2",
"app_install_id": "834C9D1B-D968-40F7-9254-4449D185B7DA"
}
```
**Forced error Explore feed content source when refreshing explore (invalid URL)**
```
{
"is_temp": false,
"code": "-1000",
"category": "WMFFramework",
"domain": "NSURLErrorDomain",
"dt": "2026-02-10T23:43:24Z",
"app_session_id": "f57f8aacc7f51070544e",
"primary_language": "test2",
"details": "stack_trace:4 WMF 0x000000010753f0ec __61-[WMFFeedContentSource fetchContentForDate:force:completion:]_block_invoke + 196 | 5 WMF 0x000000010756b594 __75-[WMFFeedContentFetcher fetchFeedContentForURL:date:force:failure:success:]_block_invoke.34 + 116 | 6 WMF 0x000000010770ad10 $sSo12NSDictionaryCSgSo17NSHTTPURLResponseCSgSo7NSErrorCSgIeyByyy_SDySSypGSgAFs5Error_pSgIegggg_TR + 256",
"is_anon": true,
"platform": "ios",
"$schema": "/analytics/mobile_apps/app_error/1.0.0",
"meta": {
"stream": "app_error",
"id": "08419BBA-B8C4-4E7A-AF81-9F3BD7514F13"
},
"app_install_id": "834C9D1B-D968-40F7-9254-4449D185B7DA"
}
```
**Forced HCaptcha error for missing config file**
```
{
"is_anon": true,
"wiki_id": "test2wiki",
"dt": "2026-02-10T23:43:58Z",
"details": "stack_trace:2 Wikipedia.debug.dylib 0x00000001045eac3c $s9Wikipedia32WMFAccountCreationViewControllerC15displayHCaptcha33_2A86BEF4F6C53BD8B43A95DC18FB51FELLyyFys5Error_pcfU0_ + 824 | 3 Wikipedia.debug.dylib 0x000000010457bd18 $s9Wikipedia25WMFHCaptchaViewControllerC13setupHCaptcha33_AAE7FD7C57D438512646C9BDB8B46B1DLLyyF + 172 | 4 Wikipedia.debug.dylib 0x000000010457a990 $s9Wikipedia25WMFHCaptchaViewControllerC13viewDidAppearyySbF + 128",
"app_install_id": "834C9D1B-D968-40F7-9254-4449D185B7DA",
"$schema": "/analytics/mobile_apps/app_error/1.0.0",
"meta": {
"id": "44540C60-EF4C-450E-949B-E7A650D8EDA3",
"stream": "app_error"
},
"app_session_id": "f57f8aacc7f51070544e",
"primary_language": "test2",
"domain": "Wikipedia.WMFHCaptchaViewController.CustomError",
"platform": "ios",
"is_temp": false,
"code": "hCaptchaMissingConfig",
"category": "AppSide"
}
```