{"record":{"id":"fe1a474bca87bf46","repo":"skylot/jadx","slug":"unexpected-visibility-flag","errorCode":null,"errorMessage":"Unexpected visibility flag: ","messagePattern":"Unexpected visibility flag: ","errorType":"exception","errorClass":"JadxRuntimeException","httpStatus":null,"severity":"error","filePath":"jadx-core/src/main/java/jadx/core/dex/info/AccessInfo.java","lineNumber":87,"sourceCode":"\t\tint otherVis = otherAccInfo.accFlags & VISIBILITY_FLAGS;\n\t\tif (thisVis == otherVis) {\n\t\t\treturn false;\n\t\t}\n\t\treturn orderedVisibility(thisVis) < orderedVisibility(otherVis);\n\t}\n\n\tprivate static int orderedVisibility(int flag) {\n\t\tswitch (flag) {\n\t\t\tcase AccessFlags.PRIVATE:\n\t\t\t\treturn 1;\n\t\t\tcase 0: // package-private\n\t\t\t\treturn 2;\n\t\t\tcase AccessFlags.PROTECTED:\n\t\t\t\treturn 3;\n\t\t\tcase AccessFlags.PUBLIC:\n\t\t\t\treturn 4;\n\t\t\tdefault:\n\t\t\t\tthrow new JadxRuntimeException(\"Unexpected visibility flag: \" + flag);\n\t\t}\n\t}\n\n\tpublic boolean isPublic() {\n\t\treturn (accFlags & AccessFlags.PUBLIC) != 0;\n\t}\n\n\tpublic boolean isProtected() {\n\t\treturn (accFlags & AccessFlags.PROTECTED) != 0;\n\t}\n\n\tpublic boolean isPrivate() {\n\t\treturn (accFlags & AccessFlags.PRIVATE) != 0;\n\t}\n\n\tpublic boolean isPackagePrivate() {\n\t\treturn (accFlags & VISIBILITY_FLAGS) == 0;\n\t}","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/skylot/jadx/blob/e738a26571d02919f01df40de93bc9a44dee4e18/jadx-core/src/main/java/jadx/core/dex/info/AccessInfo.java#L69-L105","documentation":"Thrown by AccessInfo.orderedVisibility, which orders the four legal JVM visibility flags. The switch accepts only AccessFlags.PRIVATE, 0 (package-private), AccessFlags.PROTECTED, AccessFlags.PUBLIC; any other int (e.g. a combined mask like PUBLIC|PROTECTED, or a non-visibility bit) hits the default. It enforces that visibility comparisons see exactly one canonical flag.","triggerScenarios":"orderedVisibility is called with a mask containing more than one visibility bit set, or a visibility mask that includes non-visibility bits, or a fully-zero-visibility-but-non-canonical value. Reachable from AccessInfo's visibility-sorting/comparison logic on access flags that violate the JVM invariant of exactly one visibility flag.","commonSituations":"Malformed bytecode with illegal access flag combinations; obfuscators that set conflicting visibility bits; manually-crafted DEX; bugs in flag extraction that pass the raw accFlags instead of just the visibility portion.","solutions":["Mask to the visibility bits before calling orderedVisibility: use AccessFlags.visibilityMask or AND with PUBLIC|PROTECTED|PRIVATE.","Ensure exactly one visibility bit is set; if multiple, pick a precedence (PRIVATE < default < PROTECTED < PUBLIC) before ordering.","Validate/normalise access flags at load time (in DexLoader/ClassNode) so downstream always sees a canonical value.","Report malformed input upstream if the bits genuinely conflict."],"exampleFix":"// before\nswitch (flag) {\n    case AccessFlags.PRIVATE: return 1;\n    case 0: return 2;\n    case AccessFlags.PROTECTED: return 3;\n    case AccessFlags.PUBLIC: return 4;\n    default: throw new JadxRuntimeException(\"Unexpected visibility flag: \" + flag);\n}\n\n// after (normalise conflicting masks to a canonical precedence)\nif ((flag & AccessFlags.PUBLIC) != 0) return 4;\nif ((flag & AccessFlags.PROTECTED) != 0) return 3;\nif ((flag & AccessFlags.PRIVATE) != 0) return 1;\nreturn 2; // package-private","handlingStrategy":"validation","validationCode":"int vis = accFlags & (AccessFlags.PUBLIC | AccessFlags.PROTECTED | AccessFlags.PRIVATE);\nint count = Integer.bitCount(vis);\nif (count != 1 && vis != 0) {\n    // conflicting bits - normalise before ordering\n    vis = normaliseVisibility(accFlags);\n}","typeGuard":"static boolean isCanonicalVisibility(int flag) {\n    return flag == AccessFlags.PUBLIC || flag == AccessFlags.PROTECTED\n        || flag == AccessFlags.PRIVATE || flag == 0;\n}","tryCatchPattern":"int order;\ntry {\n    order = AccessInfo.orderedVisibility(flag);\n} catch (JadxRuntimeException e) {\n    order = defaultVisibilityOrder(flag);\n}","preventionTips":["Mask to visibility bits and normalise to a single canonical flag before ordering.","Validate access flags at load time so downstream sees well-formed values.","Reject or repair conflicting visibility bits from obfuscated inputs."],"tags":["access-flags","bytecode","invariant","validation"],"backgroundTag":null,"analyzedSha":"e738a26571d02919f01df40de93bc9a44dee4e18","analyzedAt":"2026-08-14T00:10:24.238Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}