What happens
Registering a contract in PXE fails with:
verification key has wrong size: expected 5216, got 4576
Two byte counts, and nothing else. No contract, no function, and no hint that the artifact is what's wrong rather than the contract source.
Still the case on v5.1.0, the latest release at the time of writing (line references below are pinned to that tag).
Why it can't be fixed where it's thrown
The throw is in barretenberg, bbapi_shared.hpp#L41-L48:
template <typename VK> inline void validate_vk_size(const std::vector<uint8_t>& vk_bytes)
{
const size_t expected_size = VK::calc_num_data_types() * sizeof(bb::fr);
if (vk_bytes.size() != expected_size) {
throw_or_abort("verification key has wrong size: expected " + std::to_string(expected_size) + ", got " +
std::to_string(vk_bytes.size()));
}
}
(duplicated at chonk/chonk_step_processor.cpp.)
That function only receives bytes, so it genuinely cannot name a contract — this is not a bb bug.
Worth noting you already appear to be moving this way: master (post-v5.1.0) adds a labelled sibling, has_expected_vk_size, which does print an identifier. But its labels are bb-level operations ("ChonkVerify", "ChonkVerifyFromFields", "ChonkBatchVerify") — bb has no way to know an application-level name, and the unlabelled validate_vk_size is still the path that fires for contract registration.
Where the names do exist
The artifact-conversion layer already has the missing context — contract_artifact.ts#L237:
...(fn.verification_key ? { verificationKey: fn.verification_key } : undefined),
Both contract.name and fn.name are in scope there. The same file already formats exactly the identifier that would help, at #L192:
const pathToFind = `${contract.name}::${fn.name}_abi`;
and already gives a stale-artifact error with a remedy, at #L175:
`No custom attributes found for contract function ${fn.name}. Try rebuilding the contract with the latest nargo …`
The convention, the context and the tone all exist in this file. The VK-size case just doesn't get the same treatment.
Proposed change
Either validate the VK while converting the named artifact, or preserve the contract/function context around the downstream validation, so the resulting error includes:
- the contract name
- the function name
- the original expected/actual byte counts
- a suggestion to rebuild artifacts with the current toolchain
So instead of two bare numbers:
LiquidityPool::deposit — verification key has wrong size (expected 5216, got 4576).
This artifact may be stale or compiled with an incompatible toolchain version; rebuild it with the current toolchain.
The contract and function name alone do most of the work, because they reframe the problem from "something is wrong with my contract" to "this artifact is stale".
What it cost us
We run a DEX on testnet (5.0.0, Nargo deps pinned to tag v5.0.0). During our 4.3.1 → 5.0.0 migration the v5 toolchain produced 5216-byte private-function keys, while two of our five committed artifacts still carried 4576-byte ones.
Those artifacts were already tracked in git; a local nargo compile modified them and the modification was never committed. So the developer's working tree was correct while every build from a clean checkout remained broken. Because the other three contracts were fine, it looked like a per-contract logic problem rather than a build-hygiene issue. Our deployed testnet stack was unavailable for 13 days.
The diagnosis, once we thought to look, was mechanical: base64-decode functions[].verification_key and compare byte lengths against git show HEAD:<path>. But nothing in the error pointed at build outputs, so that is not where we looked.
Environment
- Hit on
aztec / @aztec/* 5.0.0, Nargo deps at tag v5.0.0; contracts compiled via the aztecprotocol/aztec:5.0.0 Docker image
- Re-checked against
v5.1.0 before filing — the throw site and the TS conversion are both unchanged there
- Reproduced at PXE contract registration in both an aggregator daemon and a faucet service
- Affected: 3 private functions across 2 contracts, all 4576 bytes where 5216 was expected
What happens
Registering a contract in PXE fails with:
Two byte counts, and nothing else. No contract, no function, and no hint that the artifact is what's wrong rather than the contract source.
Still the case on
v5.1.0, the latest release at the time of writing (line references below are pinned to that tag).Why it can't be fixed where it's thrown
The throw is in barretenberg,
bbapi_shared.hpp#L41-L48:(duplicated at
chonk/chonk_step_processor.cpp.)That function only receives bytes, so it genuinely cannot name a contract — this is not a bb bug.
Worth noting you already appear to be moving this way:
master(post-v5.1.0) adds a labelled sibling,has_expected_vk_size, which does print an identifier. But its labels are bb-level operations ("ChonkVerify","ChonkVerifyFromFields","ChonkBatchVerify") — bb has no way to know an application-level name, and the unlabelledvalidate_vk_sizeis still the path that fires for contract registration.Where the names do exist
The artifact-conversion layer already has the missing context —
contract_artifact.ts#L237:Both
contract.nameandfn.nameare in scope there. The same file already formats exactly the identifier that would help, at#L192:and already gives a stale-artifact error with a remedy, at
#L175:`No custom attributes found for contract function ${fn.name}. Try rebuilding the contract with the latest nargo …`The convention, the context and the tone all exist in this file. The VK-size case just doesn't get the same treatment.
Proposed change
Either validate the VK while converting the named artifact, or preserve the contract/function context around the downstream validation, so the resulting error includes:
So instead of two bare numbers:
The contract and function name alone do most of the work, because they reframe the problem from "something is wrong with my contract" to "this artifact is stale".
What it cost us
We run a DEX on testnet (
5.0.0, Nargo deps pinned to tagv5.0.0). During our 4.3.1 → 5.0.0 migration the v5 toolchain produced 5216-byte private-function keys, while two of our five committed artifacts still carried 4576-byte ones.Those artifacts were already tracked in git; a local
nargo compilemodified them and the modification was never committed. So the developer's working tree was correct while every build from a clean checkout remained broken. Because the other three contracts were fine, it looked like a per-contract logic problem rather than a build-hygiene issue. Our deployed testnet stack was unavailable for 13 days.The diagnosis, once we thought to look, was mechanical: base64-decode
functions[].verification_keyand compare byte lengths againstgit show HEAD:<path>. But nothing in the error pointed at build outputs, so that is not where we looked.Environment
aztec/@aztec/*5.0.0, Nargo deps at tagv5.0.0; contracts compiled via theaztecprotocol/aztec:5.0.0Docker imagev5.1.0before filing — the throw site and the TS conversion are both unchanged there