datahaven-xyz/datahaven · critical · Error
InvalidUpgradeParameters
InvalidUpgradeParameters
Error message
InvalidUpgradeParameters
What it means
The legacy system pallet's `upgrade` extrinsic throws `Error::InvalidUpgradeParameters` under the same rule as system-v2: `impl_address` or `impl_code_hash` must not be zero. This variant uses `ensure_root` instead of a governance origin, but rejects zeroed upgrade targets to prevent bricking the system contract.
Solutions
- Deploy the new implementation and pass its actual address and keccak code hash.
- Add pre-dispatch validation in the sudo script: fail fast if either value is zero.
- Double-check call argument order when encoding the extrinsic.
Example fix
// before System::upgrade(sudo_origin, H160::zero(), impl_code_hash, None)?; // after let addr = H160::from_slice(&deployed_address_bytes); assert!(!addr.is_zero() && !impl_code_hash.is_zero()); System::upgrade(sudo_origin, addr, impl_code_hash, None)?;
Defensive patterns
Strategy: validation
Validate before calling
if (implAddress === H160::zero() || implCodeHash === H256::zero()) { bail!("zero upgrade target"); } Type guard
fn is_valid_upgrade_target(addr: H160, hash: H256) -> bool { !addr.is_zero() && !hash.is_zero() } Try / catch
match System::upgrade(sudo_origin, impl_address, impl_code_hash, initializer) { Err(Error::InvalidUpgradeParameters) => { eprintln!("zeroed impl params"); abort(); }, r => r? } Prevention
- Deploy first, upgrade second — never hand-craft zero placeholders
- Unit-test sudo upgrade scripts with real artifacts
- Assert non-zero values before encode/dispatch
- Rehearse upgrades on stagenet with identical scripts
When it happens
Trigger: Calling `upgrade(origin, impl_address, impl_code_hash, initializer)` with sudo/root origin while `impl_address == H160::zero()` or `impl_code_hash == H256::zero()`.
Common situations: Sudo scripts passing default/placeholder H160::zero() or H256::zero() because the implementation contract was never deployed; copy-pasted upgrade calls with zeroed fields; test fixtures forgetting to fill in real deployment artifacts.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
AI-assisted analysis of datahaven-xyz/datahaven@edcb13dbbc (2026-09-13).
Data as JSON: /api/errors/c740c735f28a1930.
Report an issue: GitHub.
Appendix: source
Thrown at operator/pallets/system/src/lib.rs:281
/// contract
///
/// Fee required: No
///
/// - `origin`: Must be `Root`.
/// - `impl_address`: The address of the implementation contract.
/// - `impl_code_hash`: The codehash of the implementation contract.
/// - `initializer`: Optionally call an initializer on the implementation contract.
#[pallet::call_index(0)]
#[pallet::weight((T::WeightInfo::upgrade(), DispatchClass::Operational))]
pub fn upgrade(
origin: OriginFor<T>,
impl_address: H160,
impl_code_hash: H256,
initializer: Option<Initializer>,
) -> DispatchResult {
ensure_root(origin)?;
ensure!(
!impl_address.eq(&H160::zero()) && !impl_code_hash.eq(&H256::zero()),
Error::<T>::InvalidUpgradeParameters
);
let initializer_params_hash: Option<H256> = initializer
.as_ref()
.map(|i| H256::from(blake2_256(i.params.as_ref())));
let command = Command::Upgrade {
impl_address,
impl_code_hash,
initializer,
};
Self::send(PRIMARY_GOVERNANCE_CHANNEL, command, PaysFee::<T>::No)?;
Self::deposit_event(Event::<T>::Upgrade {
impl_address,
impl_code_hash,
initializer_params_hash,View on GitHub (pinned to edcb13dbbc)