{"record":{"id":"8beeb954540bdfca","repo":"DrKLO/Telegram","slug":"unknown-update-op-type-for","errorCode":null,"errorMessage":"Unknown update op type for {}","messagePattern":"Unknown update op type for (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"critical","filePath":"TMessagesProj/src/main/java/androidx/recyclerview/widget/AdapterHelper.java","lineNumber":489,"sourceCode":"            Log.d(TAG, \"postponing \" + op);\n        }\n        mPostponedList.add(op);\n        switch (op.cmd) {\n            case UpdateOp.ADD:\n                mCallback.offsetPositionsForAdd(op.positionStart, op.itemCount);\n                break;\n            case UpdateOp.MOVE:\n                mCallback.offsetPositionsForMove(op.positionStart, op.itemCount);\n                break;\n            case UpdateOp.REMOVE:\n                mCallback.offsetPositionsForRemovingLaidOutOrNewView(op.positionStart,\n                        op.itemCount);\n                break;\n            case UpdateOp.UPDATE:\n                mCallback.markViewHoldersUpdated(op.positionStart, op.itemCount, op.payload);\n                break;\n            default:\n                throw new IllegalArgumentException(\"Unknown update op type for \" + op);\n        }\n    }\n\n    boolean hasPendingUpdates() {\n        return mPendingUpdates.size() > 0;\n    }\n\n    boolean hasAnyUpdateTypes(int updateTypes) {\n        return (mExistingUpdateTypes & updateTypes) != 0;\n    }\n\n    int findPositionOffset(int position) {\n        return findPositionOffset(position, 0);\n    }\n\n    int findPositionOffset(int position, int firstPostponedItem) {\n        int count = mPostponedList.size();\n        for (int i = firstPostponedItem; i < count; ++i) {","sourceCodeStart":471,"sourceCodeEnd":507,"githubUrl":"https://github.com/DrKLO/Telegram/blob/45ab8f4308496e1f01026a97fcdb0d58a5274474/TMessagesProj/src/main/java/androidx/recyclerview/widget/AdapterHelper.java#L471-L507","documentation":"Thrown in consumeUpdatesInOneDeferredPass, the fallback path that applies ALL queued updates in a single pass when no pre-layout is needed. The switch handles ADD, MOVE, REMOVE, UPDATE and rejects anything else. Reaching the default means an UpdateOp in mPendingUpdates has a cmd value outside the four known constants — effectively corrupted state. Like errors 1 and 2, this is an internal invariant guard, not something a normal caller triggers directly.","triggerScenarios":"UpdateOp object reuse where cmd was set to an invalid value; a fork that added a new UpdateOp command constant without updating this switch; R8/ProGuard obfuscation collapsing distinct int constants; a custom AdapterHelper.Callback synthesizing malformed ops.","commonSituations":"Fork drift between UpdateOp.java and AdapterHelper.java; an obfuscation bug in a stripped release build; memory corruption from a native side or Unsafe usage touching the op array; concurrent enqueue of ops from multiple threads without synchronization.","solutions":["Keep UpdateOp and AdapterHelper source from the same AndroidX version in the fork.","Add keep rules for the recyclerview widget package to prevent constant inlining issues under R8.","Ensure all notify* calls originate from the main thread.","If the error is reproducible, log the op.toString() at enqueue time to find which component built the bad op."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Reject unknown op before enqueue\nstatic int requireKnownCmd(int cmd) {\n    switch (cmd) {\n        case UpdateOp.ADD:\n        case UpdateOp.MOVE:\n        case UpdateOp.REMOVE:\n        case UpdateOp.UPDATE: return cmd;\n        default: throw new IllegalArgumentException(\"bad cmd \" + cmd);\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate op.cmd at enqueue time in a fork to fail closer to the source.","Prevent R8 from merging/inlining UpdateOp constant fields.","Serialize all adapter updates on the main thread."],"tags":["recyclerview","internal-invariant","updateop","obfuscation"],"backgroundTag":null,"analyzedSha":"45ab8f4308496e1f01026a97fcdb0d58a5274474","analyzedAt":"2026-08-14T05:19:30.815Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}