ethereum/go-ethereum · critical

error decoding contract deployer hex %s: %v

Error message

error decoding contract deployer hex %s:
%v

What it means

The v2 deployment tree links dependency addresses into the deployer bytecode (replacing __$<id>__$ placeholders) and then hex-decodes the final deployerCode with hex.DecodeString after stripping the 0x prefix. If the resulting string contains non-hex characters or odd length, decoding fails and the code panics with the offending hex and the decode error — this indicates corrupted or badly generated deployment metadata, not a runtime chain condition.

Source

Thrown at accounts/abi/bind/v2/dep_tree.go:117

	// Don't re-deploy aliased or previously-deployed contracts
	if addr, ok := d.deployedAddrs[metadata.ID]; ok {
		return addr, nil
	}
	// If this contract/library depends on other libraries deploy them
	// (and their dependencies) first
	deployerCode := metadata.Bin
	for _, dep := range metadata.Deps {
		addr, err := d.linkAndDeploy(dep)
		if err != nil {
			return common.Address{}, err
		}
		// Link their deployed addresses into the bytecode to produce
		deployerCode = strings.ReplaceAll(deployerCode, "__$"+dep.ID+"$__", strings.ToLower(addr.String()[2:]))
	}
	// Finally, deploy the top-level contract.
	code, err := hex.DecodeString(deployerCode[2:])
	if err != nil {
		panic(fmt.Sprintf("error decoding contract deployer hex %s:\n%v", deployerCode[2:], err))
	}
	addr, tx, err := d.deployFn(d.inputs[metadata.ID], code)
	if err != nil {
		return common.Address{}, err
	}
	d.deployedAddrs[metadata.ID] = addr
	d.deployerTxs[metadata.ID] = tx
	return addr, nil
}

// result returns a DeploymentResult instance referencing contracts deployed
// and not including any overrides specified for this deployment.
func (d *depTreeDeployer) result() *DeploymentResult {
	// filter the override addresses from the deployed address set.
	for pattern := range d.deployedAddrs {
		if _, ok := d.deployerTxs[pattern]; !ok {
			delete(d.deployedAddrs, pattern)
		}

View on GitHub (pinned to 6bb0588ad8)

Solutions

  1. Regenerate the deployment metadata/binaries from a clean build (solc + abigen/bind tooling) instead of patching hex by hand.
  2. Verify every __$id$__ placeholder in metadata.Bin has a matching dependency in metadata.Deps so substitution leaves pure hex.
  3. Sanity-check the string before deploy: even length and only [0-9a-fA-F] after stripping 0x.
  4. Inspect the panic text: it prints the exact bad hex, showing where corruption begins.

Example fix

// before
meta.Bin = strings.Replace(meta.Bin, "__$lib__$__", "0x9a0f...", 1) // embeds 0x -> invalid hex

// after
meta.Bin = strings.Replace(meta.Bin, "__$lib__$__", "9a0f...", 1) // bare hex, no 0x
Defensive patterns

Strategy: validation

Validate before calling

func validHexCode(code string) bool {
	c := strings.TrimPrefix(code, "0x")
	if len(c)%2 != 0 {
		return false
	}
	for _, r := range c {
		if !strings.ContainsRune("0123456789abcdefABCDEF", r) {
			return false
		}
	}
	return true
}
// guard: if !validHexCode(strings.ReplaceAll(meta.Bin, placeholder, bareHexAddr)) { return errors.New("corrupt deployer bin") }

Type guard

func isLinkedBytecode(bin string) bool {
	return !strings.Contains(bin, "__$") && validHexCode(bin)
}

Try / catch

defer func() {
	if r := recover(); r != nil {
		if msg, _ := r.(string); strings.HasPrefix(msg, "error decoding contract deployer hex") {
			return common.Address{}, errors.New("deployer bytecode is not valid hex; regenerate bind metadata")
		}
		panic(r)
	}
}()

Prevention

When it happens

Trigger: deployFn path where metadata.Bin contains invalid hex after dependency substitution: an unresolved/misspelled placeholder, a bin artifact that was truncated or contains 'undefined' from a JS build step, or manual editing of the linked bytecode string.

Common situations: Feeding bind v2 DeploymentMetadata assembled by hand or by a buggy codegen step; solc output post-processing that mangles the bin (link placeholders replaced with address strings including '0x' or empty values); partial file writes leaving truncated hex.

Related errors


AI-assisted analysis of ethereum/go-ethereum@6bb0588ad8 (2026-08-15). Data as JSON: /api/errors/252d66fda7666593. Report an issue: GitHub.