From 6122e6a9a67cf526de7ea9de6a1f48e538635af7 Mon Sep 17 00:00:00 2001 From: Roman Zavarnitsyn Date: Tue, 10 Mar 2026 15:27:48 +0100 Subject: [PATCH 1/7] fix(proguard): Accept mapping files without line number ranges ProGuard/R8 mapping files that contain only class and method name mappings (no line number ranges) are valid and can still deobfuscate stacktraces. Previously these were rejected with "doesn't contain any line mappings", which prevented deobfuscation entirely. Fixes https://github.com/getsentry/sentry-java/issues/5143 Co-Authored-By: Claude Opus 4.6 --- crates/symbolicator-proguard/src/interface.rs | 5 -- crates/symbolicator-proguard/src/service.rs | 4 - .../src/symbolication.rs | 4 +- .../tests/integration/proguard.rs | 58 +++++++++++++ ...ation__proguard__no_line_info_mapping.snap | 32 ++++++++ .../proguard/no_line_info/proguard.txt | 81 +++++++++++++++++++ 6 files changed, 172 insertions(+), 12 deletions(-) create mode 100644 crates/symbolicator-proguard/tests/integration/snapshots/integration__proguard__no_line_info_mapping.snap create mode 100644 tests/fixtures/proguard/no_line_info/proguard.txt diff --git a/crates/symbolicator-proguard/src/interface.rs b/crates/symbolicator-proguard/src/interface.rs index 28945dfa9..d51e292fb 100644 --- a/crates/symbolicator-proguard/src/interface.rs +++ b/crates/symbolicator-proguard/src/interface.rs @@ -165,8 +165,6 @@ pub enum ProguardErrorKind { Missing, /// The file is invalid according to [`is_valid`](proguard::ProguardMapping::is_valid). Invalid, - /// The file doesn't contain line mapping information. - NoLineInfo, } impl fmt::Display for ProguardErrorKind { @@ -174,9 +172,6 @@ impl fmt::Display for ProguardErrorKind { match self { ProguardErrorKind::Missing => write!(f, "The proguard mapping file is missing."), ProguardErrorKind::Invalid => write!(f, "The proguard mapping file is invalid."), - ProguardErrorKind::NoLineInfo => { - write!(f, "The proguard mapping file does not contain line info.") - } } } } diff --git a/crates/symbolicator-proguard/src/service.rs b/crates/symbolicator-proguard/src/service.rs index 5fc4bbe01..d820352c9 100644 --- a/crates/symbolicator-proguard/src/service.rs +++ b/crates/symbolicator-proguard/src/service.rs @@ -176,10 +176,6 @@ impl CacheItemRequest for FetchProguard { Err(CacheError::Malformed( "The file is not a valid ProGuard file".into(), )) - } else if !mapping.has_line_info() { - Err(CacheError::Malformed( - "The ProGuard file doesn't contain any line mappings".into(), - )) } else { let cache_temp_file = tempfile_in_parent(temp_file)?; let mut writer = BufWriter::new(cache_temp_file); diff --git a/crates/symbolicator-proguard/src/symbolication.rs b/crates/symbolicator-proguard/src/symbolication.rs index 20bbeaef9..da692fc46 100644 --- a/crates/symbolicator-proguard/src/symbolication.rs +++ b/crates/symbolicator-proguard/src/symbolication.rs @@ -80,9 +80,6 @@ impl ProguardService { let kind = match e { CacheError::Malformed(msg) => match msg.as_str() { "The file is not a valid ProGuard file" => ProguardErrorKind::Invalid, - "The ProGuard file doesn't contain any line mappings" => { - ProguardErrorKind::NoLineInfo - } _ => unreachable!(), }, _ => ProguardErrorKind::Missing, @@ -2552,4 +2549,5 @@ some.Class -> b: index: 19 "); } + } diff --git a/crates/symbolicator-proguard/tests/integration/proguard.rs b/crates/symbolicator-proguard/tests/integration/proguard.rs index b57f137f9..61eac04f5 100644 --- a/crates/symbolicator-proguard/tests/integration/proguard.rs +++ b/crates/symbolicator-proguard/tests/integration/proguard.rs @@ -545,3 +545,61 @@ async fn test_rewrite_frames() { let response_npe = symbolication.symbolicate_jvm(request_npe).await; assert_snapshot!(response_npe); } + +#[tokio::test] +async fn test_no_line_info_mapping() { + symbolicator_test::setup(); + let (symbolication, _cache_dir) = setup_service(|_| ()); + let (_srv, source) = proguard_server("no_line_info", |_url, _query| { + json!([{ + "id":"proguard.txt", + "uuid":"246fb328-fc4e-406a-87ff-fc35f6149d8f", + "debugId":"246fb328-fc4e-406a-87ff-fc35f6149d8f", + "codeId":null, + "cpuName":"any", + "objectName":"proguard-mapping", + "symbolType":"proguard", + "headers": { + "Content-Type":"text/x-proguard+plain" + }, + "size":1000, + "sha1":"0000000000000000000000000000000000000000", + "dateCreated":"2024-02-14T10:49:38.770116Z", + "data":{ + "features":["mapping"] + } + }]) + }); + + let source = SourceConfig::Sentry(Arc::new(source)); + + // Mapping file has no line number ranges — only class/method name mappings. + // Previously rejected with "doesn't contain any line mappings". + let frames = r#"[{ + "function": "kc", + "module": "yy.xv", + "lineno": 42, + "index": 0 + }, { + "function": "kV", + "module": "yy.Fv", + "lineno": 123, + "index": 1 + }, { + "function": "VF", + "module": "yy.zX", + "index": 2 + }]"#; + + let request = make_jvm_request( + source, + r#"{"type": "RuntimeException", "module": "java.lang"}"#, + frames, + r#"[{"uuid": "246fb328-fc4e-406a-87ff-fc35f6149d8f", "type": "proguard"}]"#, + None, + ); + + let response = symbolication.symbolicate_jvm(request).await; + + assert_snapshot!(response); +} diff --git a/crates/symbolicator-proguard/tests/integration/snapshots/integration__proguard__no_line_info_mapping.snap b/crates/symbolicator-proguard/tests/integration/snapshots/integration__proguard__no_line_info_mapping.snap new file mode 100644 index 000000000..1c70dd2d5 --- /dev/null +++ b/crates/symbolicator-proguard/tests/integration/snapshots/integration__proguard__no_line_info_mapping.snap @@ -0,0 +1,32 @@ +--- +source: crates/symbolicator-proguard/tests/integration/proguard.rs +expression: response +--- +exceptions: + - type: RuntimeException + module: java.lang +stacktraces: + - exception: + type: RuntimeException + module: java.lang + frames: + - function: checkMessageInitialized + filename: AbstractParser.java + module: com.google.protobuf.AbstractParser + abs_path: AbstractParser.java + lineno: 42 + index: 0 + - function: ensureIsMutable + filename: AbstractProtobufList.java + module: com.google.protobuf.AbstractProtobufList + abs_path: AbstractProtobufList.java + lineno: 123 + index: 1 + - function: coroutineBoundary + filename: ArtificialStackFrames.java + module: _COROUTINE.ArtificialStackFrames + abs_path: ArtificialStackFrames.java + lineno: 0 + index: 2 +classes: {} +errors: [] diff --git a/tests/fixtures/proguard/no_line_info/proguard.txt b/tests/fixtures/proguard/no_line_info/proguard.txt new file mode 100644 index 000000000..ea52ebb22 --- /dev/null +++ b/tests/fixtures/proguard/no_line_info/proguard.txt @@ -0,0 +1,81 @@ +# {'id':'com.android.tools.r8.mapping','version':'1.0'} +_COROUTINE.ArtificialStackFrames -> yy.zX: + android.content.Context appContext -> Xc + java.lang.Object contentProviderStarted -> kc + java.lang.String guardsInvoked -> zc + boolean _COROUTINE.ArtificialStackFrames.isSupported() -> GV + java.lang.StackTraceElement _COROUTINE.ArtificialStackFrames.coroutineBoundary() -> VF + java.lang.StackTraceElement _COROUTINE.ArtificialStackFrames.coroutineCreation() -> XF +_COROUTINE.CoroutineDebuggingKt -> yy.Lr: + java.lang.StackTraceElement _COROUTINE.CoroutineDebuggingKt.access$artificialFrame(java.lang.Throwable,java.lang.String) -> kc +_COROUTINE._BOUNDARY -> yy.lX: + int _COROUTINE._BOUNDARY.decodeVarint64(long,byte[],int,com.google.protobuf.ArrayDecoders$Registers) -> uG +_COROUTINE._CREATION -> yy.QG: +com.google.common.util.concurrent.ListenableFuture -> yy.Pv: +com.google.protobuf.AbstractMessageLite -> yy.Hv: +com.google.protobuf.AbstractMessageLite$Builder -> yy.Ov: +com.google.protobuf.AbstractMessageLite$Builder$LimitedInputStream -> yy.pv: + int limit -> Xc + int $stable -> kc + com.google.protobuf.InvalidProtocolBufferException com.google.protobuf.AbstractMessageLite$Builder$LimitedInputStream.parseFailure() -> xc +com.google.protobuf.AbstractMessageLite$InternalOneOfEnum -> yy.ov: +com.google.protobuf.AbstractParser -> yy.xv: + com.google.protobuf.ExtensionRegistryLite EMPTY_REGISTRY -> Xc + java.lang.Object com.google.protobuf.AbstractParser.parseFrom(byte[],com.google.protobuf.ExtensionRegistryLite) -> BAc + java.lang.Object com.google.protobuf.AbstractParser.parseFrom(com.google.protobuf.CodedInputStream) -> DAc + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.parseFrom(java.io.InputStream,com.google.protobuf.ExtensionRegistryLite) -> DW + java.lang.Object com.google.protobuf.AbstractParser.parseDelimitedFrom(java.io.InputStream) -> GAc + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.parseFrom(java.io.InputStream) -> GW + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.parsePartialFrom(byte[]) -> HW + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.parsePartialFrom(byte[],int,int) -> IW + java.lang.Object com.google.protobuf.AbstractParser.parsePartialFrom(byte[],com.google.protobuf.ExtensionRegistryLite) -> JAc + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.parseFrom(byte[]) -> JW + java.lang.Object com.google.protobuf.AbstractParser.parseFrom(byte[],int,int) -> KAc + java.lang.Object com.google.protobuf.AbstractParser.parsePartialFrom(byte[]) -> OAc + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.parseFrom(com.google.protobuf.ByteString,com.google.protobuf.ExtensionRegistryLite) -> OW + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.parseFrom(com.google.protobuf.CodedInputStream,com.google.protobuf.ExtensionRegistryLite) -> PW + java.lang.Object com.google.protobuf.AbstractParser.parseFrom(java.io.InputStream,com.google.protobuf.ExtensionRegistryLite) -> RAc + java.lang.Object com.google.protobuf.AbstractParser.parsePartialFrom(java.io.InputStream) -> SAc + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.parsePartialFrom(byte[],int,int,com.google.protobuf.ExtensionRegistryLite) -> TW + java.lang.Object com.google.protobuf.AbstractParser.parsePartialFrom(java.io.InputStream,com.google.protobuf.ExtensionRegistryLite) -> UAc + java.lang.Object com.google.protobuf.AbstractParser.parseDelimitedFrom(java.io.InputStream,com.google.protobuf.ExtensionRegistryLite) -> VAc + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.parsePartialDelimitedFrom(java.io.InputStream) -> VW + java.lang.Object com.google.protobuf.AbstractParser.parseFrom(java.nio.ByteBuffer) -> XAc + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.parsePartialFrom(java.io.InputStream) -> XW + com.google.protobuf.UninitializedMessageException com.google.protobuf.AbstractParser.newUninitializedMessageException(com.google.protobuf.MessageLite) -> Xc + java.lang.Object com.google.protobuf.AbstractParser.parseFrom(byte[],int,int,com.google.protobuf.ExtensionRegistryLite) -> YAc + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.parseFrom(java.nio.ByteBuffer) -> YW + java.lang.Object com.google.protobuf.AbstractParser.parsePartialDelimitedFrom(java.io.InputStream) -> ZAc + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.parseFrom(java.nio.ByteBuffer,com.google.protobuf.ExtensionRegistryLite) -> ZW + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.parseDelimitedFrom(java.io.InputStream) -> aq + java.lang.Object com.google.protobuf.AbstractParser.parsePartialFrom(com.google.protobuf.ByteString) -> bAc + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.parseFrom(byte[],com.google.protobuf.ExtensionRegistryLite) -> dW + java.lang.Object com.google.protobuf.AbstractParser.parsePartialFrom(com.google.protobuf.CodedInputStream) -> eAc + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.parsePartialFrom(com.google.protobuf.CodedInputStream) -> eW + java.lang.Object com.google.protobuf.AbstractParser.parsePartialFrom(com.google.protobuf.ByteString,com.google.protobuf.ExtensionRegistryLite) -> gAc + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.parsePartialFrom(com.google.protobuf.ByteString) -> gW + java.lang.Object com.google.protobuf.AbstractParser.parsePartialDelimitedFrom(java.io.InputStream,com.google.protobuf.ExtensionRegistryLite) -> hAc + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.parseFrom(com.google.protobuf.CodedInputStream) -> hW + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.parsePartialFrom(byte[],com.google.protobuf.ExtensionRegistryLite) -> iW + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.parseFrom(byte[],int,int,com.google.protobuf.ExtensionRegistryLite) -> jW + java.lang.Object com.google.protobuf.AbstractParser.parseFrom(com.google.protobuf.CodedInputStream,com.google.protobuf.ExtensionRegistryLite) -> kAc + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.checkMessageInitialized(com.google.protobuf.MessageLite) -> kc + java.lang.Object com.google.protobuf.AbstractParser.parseFrom(com.google.protobuf.ByteString,com.google.protobuf.ExtensionRegistryLite) -> lAc + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.parsePartialFrom(java.io.InputStream,com.google.protobuf.ExtensionRegistryLite) -> lW + java.lang.Object com.google.protobuf.AbstractParser.parsePartialFrom(byte[],int,int) -> oAc + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.parsePartialFrom(com.google.protobuf.ByteString,com.google.protobuf.ExtensionRegistryLite) -> oW + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.parseFrom(com.google.protobuf.ByteString) -> pW + java.lang.Object com.google.protobuf.AbstractParser.parseFrom(java.io.InputStream) -> rAc + java.lang.Object com.google.protobuf.AbstractParser.parseFrom(byte[]) -> sAc + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.parseFrom(byte[],int,int) -> tW + java.lang.Object com.google.protobuf.AbstractParser.parseFrom(java.nio.ByteBuffer,com.google.protobuf.ExtensionRegistryLite) -> vAc + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.parseDelimitedFrom(java.io.InputStream,com.google.protobuf.ExtensionRegistryLite) -> vW + java.lang.Object com.google.protobuf.AbstractParser.parsePartialFrom(byte[],int,int,com.google.protobuf.ExtensionRegistryLite) -> wAc + java.lang.Object com.google.protobuf.AbstractParser.parseFrom(com.google.protobuf.ByteString) -> zAc + com.google.protobuf.MessageLite com.google.protobuf.AbstractParser.parsePartialDelimitedFrom(java.io.InputStream,com.google.protobuf.ExtensionRegistryLite) -> zW +com.google.protobuf.AbstractProtobufList -> yy.Fv: + boolean isMutable -> Xc + int DEFAULT_CAPACITY -> kc + boolean com.google.protobuf.AbstractProtobufList.isModifiable() -> Zf + void com.google.protobuf.AbstractProtobufList.makeImmutable() -> bf + void com.google.protobuf.AbstractProtobufList.ensureIsMutable() -> kV From 28aecb50e0524717cf124232dd9625e488fd7ae8 Mon Sep 17 00:00:00 2001 From: Roman Zavarnitsyn Date: Tue, 10 Mar 2026 15:33:20 +0100 Subject: [PATCH 2/7] fix: Remove trailing blank line to fix fmt lint Co-Authored-By: Claude Opus 4.6 --- crates/symbolicator-proguard/src/symbolication.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/symbolicator-proguard/src/symbolication.rs b/crates/symbolicator-proguard/src/symbolication.rs index da692fc46..fa4e87140 100644 --- a/crates/symbolicator-proguard/src/symbolication.rs +++ b/crates/symbolicator-proguard/src/symbolication.rs @@ -2549,5 +2549,4 @@ some.Class -> b: index: 19 "); } - } From 5dbdeeb12762db89a2082b0c04eb6b938748d510 Mon Sep 17 00:00:00 2001 From: Roman Zavarnitsyn Date: Tue, 10 Mar 2026 15:58:29 +0100 Subject: [PATCH 3/7] fix: Map all Malformed cache errors to Invalid instead of using unreachable Stale cached entries or unexpected malformed messages (e.g. decompression errors) would panic via unreachable!(). All malformed proguard files are invalid regardless of the specific error message. Co-Authored-By: Claude Opus 4.6 --- crates/symbolicator-proguard/src/symbolication.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/symbolicator-proguard/src/symbolication.rs b/crates/symbolicator-proguard/src/symbolication.rs index fa4e87140..e0a8bbd18 100644 --- a/crates/symbolicator-proguard/src/symbolication.rs +++ b/crates/symbolicator-proguard/src/symbolication.rs @@ -78,10 +78,7 @@ impl ProguardService { tracing::error!(%debug_id, "Error reading Proguard file: {e}"); } let kind = match e { - CacheError::Malformed(msg) => match msg.as_str() { - "The file is not a valid ProGuard file" => ProguardErrorKind::Invalid, - _ => unreachable!(), - }, + CacheError::Malformed(_) => ProguardErrorKind::Invalid, _ => ProguardErrorKind::Missing, }; errors.push(ProguardError { From 94e6cd9c9b1028f6dab563d278750277ff53b60c Mon Sep 17 00:00:00 2001 From: Roman Zavarnitsyn Date: Tue, 10 Mar 2026 18:09:55 +0100 Subject: [PATCH 4/7] Revert "fix: Map all Malformed cache errors to Invalid instead of using unreachable" This reverts commit 5dbdeeb12762db89a2082b0c04eb6b938748d510. --- crates/symbolicator-proguard/src/symbolication.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/symbolicator-proguard/src/symbolication.rs b/crates/symbolicator-proguard/src/symbolication.rs index e0a8bbd18..fa4e87140 100644 --- a/crates/symbolicator-proguard/src/symbolication.rs +++ b/crates/symbolicator-proguard/src/symbolication.rs @@ -78,7 +78,10 @@ impl ProguardService { tracing::error!(%debug_id, "Error reading Proguard file: {e}"); } let kind = match e { - CacheError::Malformed(_) => ProguardErrorKind::Invalid, + CacheError::Malformed(msg) => match msg.as_str() { + "The file is not a valid ProGuard file" => ProguardErrorKind::Invalid, + _ => unreachable!(), + }, _ => ProguardErrorKind::Missing, }; errors.push(ProguardError { From 8841d2b2e54942011f2638fbf8aaf1842f498add Mon Sep 17 00:00:00 2001 From: Roman Zavarnitsyn Date: Tue, 10 Mar 2026 18:10:25 +0100 Subject: [PATCH 5/7] fix: Bump proguard cache version to invalidate stale no-line-info errors Mapping files without line info were previously cached as Malformed errors. Bumping the cache version ensures those stale entries are invalidated and the files get re-processed correctly. Co-Authored-By: Claude Opus 4.6 --- crates/symbolicator-service/src/caches/versions.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/symbolicator-service/src/caches/versions.rs b/crates/symbolicator-service/src/caches/versions.rs index df581158a..5a352fcda 100644 --- a/crates/symbolicator-service/src/caches/versions.rs +++ b/crates/symbolicator-service/src/caches/versions.rs @@ -273,6 +273,9 @@ pub const BUNDLE_INDEX_CACHE_VERSIONS: CacheVersions = CacheVersions { /// Proguard Cache, with the following versions: /// +/// - `7`: Invalidate stale `Malformed` cached errors for mapping files without +/// line info that are now accepted. +/// /// - `6`: Information about whether a method has rewrite rules is now part /// of the cache format. /// @@ -288,7 +291,7 @@ pub const BUNDLE_INDEX_CACHE_VERSIONS: CacheVersions = CacheVersions { /// /// - `1`: Initial version. pub const PROGUARD_CACHE_VERSIONS: CacheVersions = CacheVersions { - current: CacheVersion::new(6, CachePathFormat::V2), + current: CacheVersion::new(7, CachePathFormat::V2), fallbacks: &[], previous: &[ CacheVersion::new(1, CachePathFormat::V1), @@ -296,6 +299,7 @@ pub const PROGUARD_CACHE_VERSIONS: CacheVersions = CacheVersions { CacheVersion::new(3, CachePathFormat::V2), CacheVersion::new(4, CachePathFormat::V2), CacheVersion::new(5, CachePathFormat::V2), + CacheVersion::new(6, CachePathFormat::V2), ], }; static_assert!(proguard::PRGCACHE_VERSION == 4); From 791efe678900a0588937505a28d8ef5929381a0e Mon Sep 17 00:00:00 2001 From: Roman Zavarnitsyn Date: Tue, 10 Mar 2026 18:29:41 +0100 Subject: [PATCH 6/7] Revert "fix: Bump proguard cache version to invalidate stale no-line-info errors" This reverts commit 8841d2b2e54942011f2638fbf8aaf1842f498add. --- crates/symbolicator-service/src/caches/versions.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/crates/symbolicator-service/src/caches/versions.rs b/crates/symbolicator-service/src/caches/versions.rs index 5a352fcda..df581158a 100644 --- a/crates/symbolicator-service/src/caches/versions.rs +++ b/crates/symbolicator-service/src/caches/versions.rs @@ -273,9 +273,6 @@ pub const BUNDLE_INDEX_CACHE_VERSIONS: CacheVersions = CacheVersions { /// Proguard Cache, with the following versions: /// -/// - `7`: Invalidate stale `Malformed` cached errors for mapping files without -/// line info that are now accepted. -/// /// - `6`: Information about whether a method has rewrite rules is now part /// of the cache format. /// @@ -291,7 +288,7 @@ pub const BUNDLE_INDEX_CACHE_VERSIONS: CacheVersions = CacheVersions { /// /// - `1`: Initial version. pub const PROGUARD_CACHE_VERSIONS: CacheVersions = CacheVersions { - current: CacheVersion::new(7, CachePathFormat::V2), + current: CacheVersion::new(6, CachePathFormat::V2), fallbacks: &[], previous: &[ CacheVersion::new(1, CachePathFormat::V1), @@ -299,7 +296,6 @@ pub const PROGUARD_CACHE_VERSIONS: CacheVersions = CacheVersions { CacheVersion::new(3, CachePathFormat::V2), CacheVersion::new(4, CachePathFormat::V2), CacheVersion::new(5, CachePathFormat::V2), - CacheVersion::new(6, CachePathFormat::V2), ], }; static_assert!(proguard::PRGCACHE_VERSION == 4); From a5bdb0287679c5cfc449d7b06828a6748ffbb985 Mon Sep 17 00:00:00 2001 From: Roman Zavarnitsyn Date: Tue, 10 Mar 2026 18:29:59 +0100 Subject: [PATCH 7/7] fix: Map all Malformed cache errors to Invalid instead of using unreachable Co-Authored-By: Claude Opus 4.6 --- crates/symbolicator-proguard/src/symbolication.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/symbolicator-proguard/src/symbolication.rs b/crates/symbolicator-proguard/src/symbolication.rs index fa4e87140..e0a8bbd18 100644 --- a/crates/symbolicator-proguard/src/symbolication.rs +++ b/crates/symbolicator-proguard/src/symbolication.rs @@ -78,10 +78,7 @@ impl ProguardService { tracing::error!(%debug_id, "Error reading Proguard file: {e}"); } let kind = match e { - CacheError::Malformed(msg) => match msg.as_str() { - "The file is not a valid ProGuard file" => ProguardErrorKind::Invalid, - _ => unreachable!(), - }, + CacheError::Malformed(_) => ProguardErrorKind::Invalid, _ => ProguardErrorKind::Missing, }; errors.push(ProguardError {