{"record":{"id":"68bf8806f0f97dd0","repo":"diem/diem","slug":"must-be-non-deletion","errorCode":null,"errorMessage":"must be non-deletion","messagePattern":"must be non-deletion","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"language/tools/move-cli/src/sandbox/commands/publish.rs","lineNumber":151,"sourceCode":"                            has_error = true;\n                        }\n                    }\n                }\n            }\n        }\n\n        if !has_error {\n            let (changeset, events) = session.finish().map_err(|e| e.into_vm_status())?;\n            assert!(events.is_empty());\n            if verbose {\n                explain_publish_changeset(&changeset, state);\n            }\n            let modules: Vec<_> = changeset\n                .into_modules()\n                .map(|(module_id, blob_opt)| {\n                    let addr_name = id_to_ident[&module_id];\n                    let ident = (module_id, addr_name);\n                    (ident, blob_opt.expect(\"must be non-deletion\"))\n                })\n                .collect();\n            state.save_modules(&modules, named_address_mapping)?;\n        }\n    } else {\n        // NOTE: the VM enforces the most strict way of module republishing and does not allow\n        // backward incompatible changes, as as result, if this flag is set, we skip the VM process\n        // and force the CLI to override the on-disk state directly\n        let mut serialized_modules = vec![];\n        for ((_, address_name_opt), module) in modules {\n            let id = module.self_id();\n            let mut module_bytes = vec![];\n            module.serialize(&mut module_bytes)?;\n            serialized_modules.push(((id, address_name_opt), module_bytes));\n        }\n        state.save_modules(&serialized_modules, named_address_mapping)?;\n    }\n","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/diem/diem/blob/fc4714a8ea273b6efe8b13dbce72ea60aad9a16c/language/tools/move-cli/src/sandbox/commands/publish.rs#L133-L169","documentation":"After a successful sandbox (non-VM) publish, the code is written via a ChangeSet. Modules are extracted with changeset.into_modules(), yielding (ModuleId, Option<Vec<u8>>) where the Option is Some for published/updated modules and None for deletions. Publish only produces additions, so the code expects(blob).expect(\"must be non-deletion\") panics with 'must be non-deletion' if a deletion (None) unexpectedly appears — indicating an internal inconsistency (a module being republished/replaced resulted in a deletion entry).","triggerScenarios":"Publishing over existing state where the sandbox changeset records a module deletion instead of an upsert — e.g. republishing a module under conditions the CLI's lenient republish path handles via changesets, and the changeset marks the old module for deletion.","commonSituations":"Republishing a module that already exists at the same address; state left in an inconsistent condition by earlier partial publishes; mixing publish modes (VM vs sandbox) on the same storage.","solutions":["Avoid republishing the same module at the same address; bump the package version or move to a new module/address.","Clear the affected module (or reset storage/) and republish cleanly from source.","Ensure you consistently use one publish path (sandbox publish vs VM) for a given storage directory.","If reproducible, report it — this is an invariant violation (expect) rather than a normal user-facing error path."],"exampleFix":"// before: republish over existing module triggers deletion entry panic\n$ move sandbox publish build/my_pkg   # module 0x42::app already in storage\nmust be non-deletion\n\n// after: remove stale storage first\n$ rm -rf storage && move sandbox publish build/my_pkg","handlingStrategy":"fallback","validationCode":"// Detect existing modules at the same addresses before a lenient republish\nfor m in built_modules {\n    if state.get_module(&m.id).is_some() {\n        warn(\"module {} already published; reset storage or bump version\", m.id);\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Don't republish identical module addresses into the same storage","Use a fresh storage dir per publish iteration","Stick to one publish path (sandbox vs VM) per storage directory"],"tags":["move","publish","changeset","invariant"],"backgroundTag":"unexpected-module-deletion","analyzedSha":"fc4714a8ea273b6efe8b13dbce72ea60aad9a16c","analyzedAt":"2026-09-04T21:07:05.890Z","contentChangedAt":"2026-09-04T21:07:05.890Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}