diem/diem · error

Found {:?} modules locally but {:?} in remote storage

Error message

Found {:?} modules locally but {:?} in remote storage

What it means

After applying the writeset, the resulting module set (old_modules) must contain exactly as many modules as the local artifact (remote_modules). A count mismatch means the writeset adds or removes a different number of modules than the artifact carries, so post-state cannot equal the on-disk release.

Source

Thrown at language/diem-tools/writeset-transaction-generator/src/release_flow/verify.rs:136

                        Ok(m) => m,
                        Err(e) => bail!("Unexpected module deserialize error {:?}", e),
                    };

                    match old_modules.insert(module_id.clone(), updated_module.clone()) {
                        Some(_) => println!("Updating existing module: {:?}", module_id),
                        None => println!("Adding new module: {:?}", module_id),
                    }
                }
            }
        }
    }

    let local_modules = remote_modules
        .into_iter()
        .map(|m| (m.self_id(), m.clone()))
        .collect::<BTreeMap<_, _>>();
    if local_modules.len() != old_modules.len() {
        bail!(
            "Found {:?} modules locally but {:?} in remote storage",
            local_modules.len(),
            old_modules.len()
        )
    }
    for (remote, local) in old_modules.values().zip(local_modules.values()) {
        if remote != local {
            bail!("Applying writeset onto the state causes module {:?} diverge from the on disk files", local.self_id())
        }
    }
    Ok(())
}

View on GitHub (pinned to fc4714a8ea)

Solutions

  1. Ensure the artifact directory contains every module the writeset publishes or updates
  2. Regenerate the writeset payload from the same complete artifact
  3. Replay against a chain state consistent with the release prerequisites

Example fix

// before
artifact_dir/standard/  // missing new module X.mv
// after
artifact_dir/standard/  // includes X.mv so counts match
Defensive patterns

Strategy: validation

Validate before calling

fn module_counts_match(artifact_modules: &[CompiledModule], old_modules: &BTreeMap<ModuleId, CompiledModule>) -> bool {
    artifact_modules.len() == old_modules.len()
}

Try / catch

match verify_payload_change(...) {
    Err(e) if e.to_string().contains("modules locally but") => {
        eprintln!("Artifact vs chain module count mismatch; regenerate payload from complete artifact");
    }
    other => other?,
}

Prevention

When it happens

Trigger: verify_payload_change compares local_modules.len() vs old_modules.len(); mismatch occurs when the payload publishes/deletes modules not accounted for by the artifact — e.g. artifact missing a newly added module, or payload including extra modules.

Common situations: Release artifact directory incomplete (missing new modules); payload generated from a different artifact version; dependency modules expected to change but absent; replay against a chain version with different module count.

Related errors


AI-assisted analysis of diem/diem@fc4714a8ea (2026-09-04). Data as JSON: /api/errors/6e37a4dbff037005. Report an issue: GitHub.