From e0ab853b4adfa39c1054d455a6ffcb2e67924cd1 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 16 Feb 2026 19:58:41 -0500 Subject: [PATCH] fix: add logging to silent try-catch blocks across codebase Add println() diagnostics to ~30 catch blocks that previously swallowed exceptions silently, making debugging impossible. Each log message includes a component tag (e.g. [ISO7816], [CEPAS], [MdST]) and the exception details. Categories of changes: - ViewModels: log + stacktrace when card/key loading fails - MdST station reader: log parse and decode failures - LocalStorage persisters: log deserialization failures - Transit factories: log identity/metadata parse failures - ISO7816 card reader: log record, binary, balance, and file read failures - ISO7816 protocol: log unexpected errors in selectByName - ISO7816 TLV: log recursive build and decode failures - CEPAS protocol: log purse and history read failures - FeliCa adapters: log transceive failures - Vicinity reader: log system info read failures - KSX6924: log hex date/datetime parse failures Catch blocks that are legitimately silent (protocol probing, resource cleanup, expected card detection failures) are left unchanged. Co-Authored-By: Claude Opus 4.6 --- .../farebot/shared/nfc/ISO7816Dispatcher.kt | 1 + .../farebot/shared/serialize/MetrodroidJsonParser.kt | 1 + .../farebot/shared/viewmodel/HistoryViewModel.kt | 2 ++ .../farebot/shared/viewmodel/KeysViewModel.kt | 2 ++ .../farebot/web/LocalStorageCardKeysPersister.kt | 3 ++- .../farebot/web/LocalStorageCardPersister.kt | 3 ++- .../farebot/base/mdst/MdstStationTableReader.kt | 2 ++ .../codebutler/farebot/card/cepas/CEPASProtocol.kt | 4 +++- .../farebot/card/felica/PN533FeliCaTagAdapter.kt | 3 ++- .../farebot/card/felica/PCSCFeliCaTagAdapter.kt | 1 + .../farebot/card/iso7816/ISO7816CardReader.kt | 11 ++++++++--- .../farebot/card/iso7816/ISO7816Protocol.kt | 1 + .../com/codebutler/farebot/card/iso7816/ISO7816TLV.kt | 2 ++ .../codebutler/farebot/card/ksx6924/KSX6924Utils.kt | 2 ++ .../farebot/card/vicinity/VicinityCardReader.kt | 3 ++- .../farebot/transit/china/ChinaTransitData.kt | 1 + .../codebutler/farebot/transit/erg/ErgTransitInfo.kt | 3 ++- .../farebot/transit/tfileap/LeapTransitFactory.kt | 1 + 18 files changed, 37 insertions(+), 9 deletions(-) diff --git a/app/src/commonMain/kotlin/com/codebutler/farebot/shared/nfc/ISO7816Dispatcher.kt b/app/src/commonMain/kotlin/com/codebutler/farebot/shared/nfc/ISO7816Dispatcher.kt index 2a912ac3b..08965a503 100644 --- a/app/src/commonMain/kotlin/com/codebutler/farebot/shared/nfc/ISO7816Dispatcher.kt +++ b/app/src/commonMain/kotlin/com/codebutler/farebot/shared/nfc/ISO7816Dispatcher.kt @@ -57,6 +57,7 @@ object ISO7816Dispatcher { return try { ISO7816CardReader.readCard(tagId, transceiver, appConfigs) } catch (e: Exception) { + println("[ISO7816Dispatcher] ISO7816 read attempt failed: $e") null } } diff --git a/app/src/commonMain/kotlin/com/codebutler/farebot/shared/serialize/MetrodroidJsonParser.kt b/app/src/commonMain/kotlin/com/codebutler/farebot/shared/serialize/MetrodroidJsonParser.kt index 15eef3523..88c05a8ef 100644 --- a/app/src/commonMain/kotlin/com/codebutler/farebot/shared/serialize/MetrodroidJsonParser.kt +++ b/app/src/commonMain/kotlin/com/codebutler/farebot/shared/serialize/MetrodroidJsonParser.kt @@ -548,6 +548,7 @@ object MetrodroidJsonParser { return try { ByteUtils.hexStringToByteArray(hex) } catch (e: Exception) { + println("[MetrodroidJsonParser] Failed to parse hex string: $e") ByteArray(0) } } diff --git a/app/src/commonMain/kotlin/com/codebutler/farebot/shared/viewmodel/HistoryViewModel.kt b/app/src/commonMain/kotlin/com/codebutler/farebot/shared/viewmodel/HistoryViewModel.kt index 41ce02d19..ac69914d0 100644 --- a/app/src/commonMain/kotlin/com/codebutler/farebot/shared/viewmodel/HistoryViewModel.kt +++ b/app/src/commonMain/kotlin/com/codebutler/farebot/shared/viewmodel/HistoryViewModel.kt @@ -156,6 +156,8 @@ class HistoryViewModel( groupedItems = groupedItems, ) } catch (e: Throwable) { + println("[HistoryViewModel] Failed to load cards: $e") + e.printStackTrace() _uiState.value = _uiState.value.copy(isLoading = false, allItems = emptyList(), groupedItems = emptyList()) } diff --git a/app/src/commonMain/kotlin/com/codebutler/farebot/shared/viewmodel/KeysViewModel.kt b/app/src/commonMain/kotlin/com/codebutler/farebot/shared/viewmodel/KeysViewModel.kt index 2c82deca8..7fbc81507 100644 --- a/app/src/commonMain/kotlin/com/codebutler/farebot/shared/viewmodel/KeysViewModel.kt +++ b/app/src/commonMain/kotlin/com/codebutler/farebot/shared/viewmodel/KeysViewModel.kt @@ -37,6 +37,8 @@ class KeysViewModel( } _uiState.value = KeysUiState(keys = keys, isLoading = false) } catch (e: Throwable) { + println("[KeysViewModel] Failed to load keys: $e") + e.printStackTrace() _uiState.value = KeysUiState(isLoading = false) } } diff --git a/app/web/src/wasmJsMain/kotlin/com/codebutler/farebot/web/LocalStorageCardKeysPersister.kt b/app/web/src/wasmJsMain/kotlin/com/codebutler/farebot/web/LocalStorageCardKeysPersister.kt index e041cca59..5bd7a0d15 100644 --- a/app/web/src/wasmJsMain/kotlin/com/codebutler/farebot/web/LocalStorageCardKeysPersister.kt +++ b/app/web/src/wasmJsMain/kotlin/com/codebutler/farebot/web/LocalStorageCardKeysPersister.kt @@ -86,7 +86,8 @@ class LocalStorageCardKeysPersister( val raw = lsGetItem(STORAGE_KEY.toJsString())?.toString() ?: return emptyList() return try { json.decodeFromString>(raw).map { it.toSavedKey() } - } catch (_: Exception) { + } catch (e: Exception) { + println("[LocalStorage] Failed to load saved keys: $e") emptyList() } } diff --git a/app/web/src/wasmJsMain/kotlin/com/codebutler/farebot/web/LocalStorageCardPersister.kt b/app/web/src/wasmJsMain/kotlin/com/codebutler/farebot/web/LocalStorageCardPersister.kt index f7227bce0..75001ca2a 100644 --- a/app/web/src/wasmJsMain/kotlin/com/codebutler/farebot/web/LocalStorageCardPersister.kt +++ b/app/web/src/wasmJsMain/kotlin/com/codebutler/farebot/web/LocalStorageCardPersister.kt @@ -86,7 +86,8 @@ class LocalStorageCardPersister( val raw = lsGetItem(STORAGE_KEY.toJsString())?.toString() ?: return emptyList() return try { json.decodeFromString>(raw).map { it.toSavedCard() } - } catch (_: Exception) { + } catch (e: Exception) { + println("[LocalStorage] Failed to load saved cards: $e") emptyList() } } diff --git a/base/src/commonMain/kotlin/com/codebutler/farebot/base/mdst/MdstStationTableReader.kt b/base/src/commonMain/kotlin/com/codebutler/farebot/base/mdst/MdstStationTableReader.kt index 77335de9f..e987ab1ad 100644 --- a/base/src/commonMain/kotlin/com/codebutler/farebot/base/mdst/MdstStationTableReader.kt +++ b/base/src/commonMain/kotlin/com/codebutler/farebot/base/mdst/MdstStationTableReader.kt @@ -88,6 +88,7 @@ class MdstStationTableReader private constructor( val (bytes, _) = readDelimitedBytes(data, absoluteOffset) ProtoBuf.decodeFromByteArray(bytes) } catch (e: Exception) { + println("[MdST] Failed to decode station $id: $e") null } } @@ -129,6 +130,7 @@ class MdstStationTableReader private constructor( readers[dbName] = reader reader } catch (e: Exception) { + println("[MdST] Failed to parse $dbName: $e") null } } diff --git a/card/cepas/src/commonMain/kotlin/com/codebutler/farebot/card/cepas/CEPASProtocol.kt b/card/cepas/src/commonMain/kotlin/com/codebutler/farebot/card/cepas/CEPASProtocol.kt index 698f0c203..c95abe9ae 100644 --- a/card/cepas/src/commonMain/kotlin/com/codebutler/farebot/card/cepas/CEPASProtocol.kt +++ b/card/cepas/src/commonMain/kotlin/com/codebutler/farebot/card/cepas/CEPASProtocol.kt @@ -42,6 +42,7 @@ internal class CEPASProtocol( ) if (result.isEmpty()) null else result } catch (ex: ISO7816Exception) { + println("[CEPAS] Failed to read purse $purseId: $ex") null } @@ -58,6 +59,7 @@ internal class CEPASProtocol( byteArrayOf(0.toByte()), ) } catch (ex: ISO7816Exception) { + println("[CEPAS] Failed to read purse history: $ex") return null } @@ -73,7 +75,7 @@ internal class CEPASProtocol( ) historyBuff = historyBuff + historyBuff2 } catch (ex: ISO7816Exception) { - // Error reading 2nd purse history + println("[CEPAS] Failed to read 2nd purse history: $ex") } return historyBuff diff --git a/card/felica/src/commonMain/kotlin/com/codebutler/farebot/card/felica/PN533FeliCaTagAdapter.kt b/card/felica/src/commonMain/kotlin/com/codebutler/farebot/card/felica/PN533FeliCaTagAdapter.kt index c418efc2f..15cca377f 100644 --- a/card/felica/src/commonMain/kotlin/com/codebutler/farebot/card/felica/PN533FeliCaTagAdapter.kt +++ b/card/felica/src/commonMain/kotlin/com/codebutler/farebot/card/felica/PN533FeliCaTagAdapter.kt @@ -146,7 +146,8 @@ class PN533FeliCaTagAdapter( private suspend fun transceiveFelica(felicaFrame: ByteArray): ByteArray? = try { pn533.inCommunicateThru(felicaFrame) - } catch (_: Exception) { + } catch (e: Exception) { + println("[PN533FeliCa] Transceive failed: $e") null } } diff --git a/card/felica/src/jvmMain/kotlin/com/codebutler/farebot/card/felica/PCSCFeliCaTagAdapter.kt b/card/felica/src/jvmMain/kotlin/com/codebutler/farebot/card/felica/PCSCFeliCaTagAdapter.kt index a537271c2..763c3d99a 100644 --- a/card/felica/src/jvmMain/kotlin/com/codebutler/farebot/card/felica/PCSCFeliCaTagAdapter.kt +++ b/card/felica/src/jvmMain/kotlin/com/codebutler/farebot/card/felica/PCSCFeliCaTagAdapter.kt @@ -172,6 +172,7 @@ class PCSCFeliCaTagAdapter( null } } catch (e: Exception) { + println("[PCSCFeliCa] Transceive failed: $e") null } } diff --git a/card/iso7816/src/commonMain/kotlin/com/codebutler/farebot/card/iso7816/ISO7816CardReader.kt b/card/iso7816/src/commonMain/kotlin/com/codebutler/farebot/card/iso7816/ISO7816CardReader.kt index e986838fe..6bae932de 100644 --- a/card/iso7816/src/commonMain/kotlin/com/codebutler/farebot/card/iso7816/ISO7816CardReader.kt +++ b/card/iso7816/src/commonMain/kotlin/com/codebutler/farebot/card/iso7816/ISO7816CardReader.kt @@ -173,6 +173,7 @@ object ISO7816CardReader { } catch (e: ISO7816Exception) { break } catch (e: Exception) { + println("[ISO7816] Record read failed at SFI $sfi, record $recordNum: $e") break } } @@ -181,7 +182,7 @@ object ISO7816CardReader { try { binaryData = protocol.readBinary(sfi) } catch (e: Exception) { - // Ignore - binary read may not be supported for this SFI + println("[ISO7816] Binary read failed for SFI $sfi: $e") } return if (records.isNotEmpty() || binaryData != null) { @@ -222,6 +223,7 @@ object ISO7816CardReader { } catch (e: ISOEOFException) { break } catch (e: Exception) { + println("[ISO7816] File record read failed: $e") break } } @@ -231,6 +233,7 @@ object ISO7816CardReader { try { protocol.readBinary() } catch (e: Exception) { + println("[ISO7816] File binary read failed: $e") null } @@ -238,6 +241,7 @@ object ISO7816CardReader { return ISO7816File(binaryData = binaryData, records = records, fci = fci) } catch (e: Exception) { + println("[ISO7816] File read failed for app: $e") return null } } @@ -260,7 +264,7 @@ object ISO7816CardReader { ) balances[i] = balance } catch (e: Exception) { - // Some balances may not be available + println("[ISO7816] Balance read failed: $e") } } return balances @@ -280,6 +284,7 @@ object ISO7816CardReader { 4, // BALANCE_RESP_LEN ) } catch (e: Exception) { + println("[ISO7816] KSX6924 purse info failed: $e") null } @@ -302,7 +307,7 @@ object ISO7816CardReader { records.add(record) } } catch (e: Exception) { - // Stop at first failure + println("[ISO7816] KSX6924 transaction record read failed: $e") } return records } diff --git a/card/iso7816/src/commonMain/kotlin/com/codebutler/farebot/card/iso7816/ISO7816Protocol.kt b/card/iso7816/src/commonMain/kotlin/com/codebutler/farebot/card/iso7816/ISO7816Protocol.kt index 56e02b2d6..ec98394cf 100644 --- a/card/iso7816/src/commonMain/kotlin/com/codebutler/farebot/card/iso7816/ISO7816Protocol.kt +++ b/card/iso7816/src/commonMain/kotlin/com/codebutler/farebot/card/iso7816/ISO7816Protocol.kt @@ -172,6 +172,7 @@ class ISO7816Protocol( } catch (e: ISO7816Exception) { null } catch (e: Exception) { + println("[ISO7816Protocol] Unexpected error in selectByName: $e") null } diff --git a/card/iso7816/src/commonMain/kotlin/com/codebutler/farebot/card/iso7816/ISO7816TLV.kt b/card/iso7816/src/commonMain/kotlin/com/codebutler/farebot/card/iso7816/ISO7816TLV.kt index 2e2c8f294..295cbe2cd 100644 --- a/card/iso7816/src/commonMain/kotlin/com/codebutler/farebot/card/iso7816/ISO7816TLV.kt +++ b/card/iso7816/src/commonMain/kotlin/com/codebutler/farebot/card/iso7816/ISO7816TLV.kt @@ -306,6 +306,7 @@ object ISO7816TLV { infoBerTLV(header + data, multihead), ) } catch (e: Exception) { + println("[ISO7816TLV] Failed to build TLV items: $e") ListItem(id.toHexDump(), data.toHexDump()) } } else { @@ -319,6 +320,7 @@ object ISO7816TLV { try { ListItemRecursive(FormattedString("TLV"), null, infoBerTLV(buf)) } catch (e: Exception) { + println("[ISO7816TLV] Failed to decode TLV node: $e") null }, ) diff --git a/card/ksx6924/src/commonMain/kotlin/com/codebutler/farebot/card/ksx6924/KSX6924Utils.kt b/card/ksx6924/src/commonMain/kotlin/com/codebutler/farebot/card/ksx6924/KSX6924Utils.kt index 1e37bc151..489575945 100644 --- a/card/ksx6924/src/commonMain/kotlin/com/codebutler/farebot/card/ksx6924/KSX6924Utils.kt +++ b/card/ksx6924/src/commonMain/kotlin/com/codebutler/farebot/card/ksx6924/KSX6924Utils.kt @@ -70,6 +70,7 @@ object KSX6924Utils { second = second, ).toInstant(tz) } catch (e: Exception) { + println("[KSX6924] Failed to parse hex datetime: $e") null } } @@ -94,6 +95,7 @@ object KSX6924Utils { return try { LocalDate(year = year, month = month, day = day) } catch (e: Exception) { + println("[KSX6924] Failed to parse hex date: $e") null } } diff --git a/card/vicinity/src/commonMain/kotlin/com/codebutler/farebot/card/vicinity/VicinityCardReader.kt b/card/vicinity/src/commonMain/kotlin/com/codebutler/farebot/card/vicinity/VicinityCardReader.kt index d2848f7bd..785f10b3c 100644 --- a/card/vicinity/src/commonMain/kotlin/com/codebutler/farebot/card/vicinity/VicinityCardReader.kt +++ b/card/vicinity/src/commonMain/kotlin/com/codebutler/farebot/card/vicinity/VicinityCardReader.kt @@ -61,7 +61,8 @@ object VicinityCardReader { } else { null } - } catch (_: Exception) { + } catch (e: Exception) { + println("[VicinityCardReader] Failed to read system info: $e") null } diff --git a/transit/china/src/commonMain/kotlin/com/codebutler/farebot/transit/china/ChinaTransitData.kt b/transit/china/src/commonMain/kotlin/com/codebutler/farebot/transit/china/ChinaTransitData.kt index 732213564..7922660d9 100644 --- a/transit/china/src/commonMain/kotlin/com/codebutler/farebot/transit/china/ChinaTransitData.kt +++ b/transit/china/src/commonMain/kotlin/com/codebutler/farebot/transit/china/ChinaTransitData.kt @@ -114,6 +114,7 @@ object ChinaTransitData { second = 0, ).toInstant(TZ) } catch (e: Exception) { + println("[ChinaTransit] Failed to parse hex date from $value: $e") null } } diff --git a/transit/erg/src/commonMain/kotlin/com/codebutler/farebot/transit/erg/ErgTransitInfo.kt b/transit/erg/src/commonMain/kotlin/com/codebutler/farebot/transit/erg/ErgTransitInfo.kt index afe5ae4be..e392bde4f 100644 --- a/transit/erg/src/commonMain/kotlin/com/codebutler/farebot/transit/erg/ErgTransitInfo.kt +++ b/transit/erg/src/commonMain/kotlin/com/codebutler/farebot/transit/erg/ErgTransitInfo.kt @@ -91,7 +91,8 @@ open class ErgTransitInfo( if (sector0 !is DataClassicSector) return null return try { ErgMetadataRecord.recordFromBytes(sector0.getBlock(2).data) - } catch (_: Exception) { + } catch (e: Exception) { + println("[ERG] Failed to parse metadata record: $e") null } } diff --git a/transit/tfi-leap/src/commonMain/kotlin/com/codebutler/farebot/transit/tfileap/LeapTransitFactory.kt b/transit/tfi-leap/src/commonMain/kotlin/com/codebutler/farebot/transit/tfileap/LeapTransitFactory.kt index f8651f35a..363cc34a4 100644 --- a/transit/tfi-leap/src/commonMain/kotlin/com/codebutler/farebot/transit/tfileap/LeapTransitFactory.kt +++ b/transit/tfi-leap/src/commonMain/kotlin/com/codebutler/farebot/transit/tfileap/LeapTransitFactory.kt @@ -48,6 +48,7 @@ class LeapTransitFactory : TransitFactory { val file6 = (app.getFile(6) as StandardDesfireFile).data TransitIdentity(FormattedString(Res.string.transit_leap_card_name), LeapTransitInfo.getSerial(file2, file6)) } catch (e: Exception) { + println("[Leap] Failed to parse identity: $e") TransitIdentity(FormattedString(Res.string.transit_leap_card_name), null) }