ethereum/go-ethereum · error · Error

Cannot send value to non-payable function

Error message

Cannot send value to non-payable function

What it means

SolidityFunction.sendTransaction refuses to send a transaction whose payload.value > 0 when the ABI entry for the method was not marked payable (this._payable false). It is a client-side guard against a transaction the EVM would revert anyway, checked before anything is broadcast.

Source

Thrown at internal/jsre/deps/web3.js:4157

            error = e;
        }

        callback(error, unpacked);
    });
};

/**
 * Should be used to sendTransaction to solidity function
 *
 * @method sendTransaction
 */
SolidityFunction.prototype.sendTransaction = function () {
    var args = Array.prototype.slice.call(arguments).filter(function (a) {return a !== undefined; });
    var callback = this.extractCallback(args);
    var payload = this.toPayload(args);

    if (payload.value > 0 && !this._payable) {
        throw new Error('Cannot send value to non-payable function');
    }

    if (!callback) {
        return this._eth.sendTransaction(payload);
    }

    this._eth.sendTransaction(payload, callback);
};

/**
 * Should be used to estimateGas of solidity function
 *
 * @method estimateGas
 */
SolidityFunction.prototype.estimateGas = function () {
    var args = Array.prototype.slice.call(arguments);
    var callback = this.extractCallback(args);
    var payload = this.toPayload(args);

View on GitHub (pinned to 6bb0588ad8)

Solutions

  1. Remove the value field from the transaction options if the function must not receive ether.
  2. If the function should accept ether, mark it payable in Solidity (function foo() payable) and redeploy.
  3. Regenerate/refresh the ABI passed to web3 so it matches the deployed contract.
  4. For plain ether transfer use address.sendTransaction or eth.sendTransaction instead of a contract method.

Example fix

// before
instance.buy({from: acct, value: web3.toWei(1, 'ether')}); // ABI not payable

// after
// Solidity: function buy() public payable
instance.buy({from: acct, value: web3.toWei(1, 'ether')});
Defensive patterns

Strategy: validation

Validate before calling

function callMethod(instance, name, opts) {
  var abi = instance.abi.filter(function (a) { return a.name === name; })[0];
  if (opts && opts.value > 0 && !abi.payable) {
    throw new Error(name + ' is not payable; remove value or mark payable in Solidity');
  }
  return instance[name](opts);
}

Type guard

function isPayableMethod(instance, name) {
  return instance.abi.some(function (a) { return a.name === name && a.payable; });
}

Try / catch

try { instance.buy({from: a, value: v}); }
catch (e) {
  if (/non-payable function/.test(e.message)) { /* drop value or redeploy payable */ }
}

Prevention

When it happens

Trigger: Calling instance.method.sendTransaction({from, value: web3.toWei(1,'ether'), gas}) or the sugar instance.method(..., {value: X}) where the ABI for method lacks 'payable': true. Filtering undefined args then building the payload leaves value > 0 and _payable false, so it throws.

Common situations: ABI from an older Solidity version (<0.4.x) where payable is not encoded for fallback, deploying with one ABI artifact and calling with another, or simply forgetting the function is non-payable when testing value transfers.

Related errors


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