ethereum/go-ethereum · error · Error

Cannot send value to non-payable constructor

Error message

Cannot send value to non-payable constructor

What it means

Filter.get() supports both sync and async styles. In synchronous mode it reads this.filterId; if the filter has not been created yet (filterId === null, creation is asynchronous), it cannot chain synchronously and throws this error telling you to pass a callback. The filter id only exists after the async creation round-trip completes.

Source

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

        var callback;

        var args = Array.prototype.slice.call(arguments);
        if (utils.isFunction(args[args.length - 1])) {
            callback = args.pop();
        }

        var last = args[args.length - 1];
        if (utils.isObject(last) && !utils.isArray(last)) {
            options = args.pop();
        }

        if (options.value > 0) {
            var constructorAbi = abi.filter(function (json) {
                return json.type === 'constructor' && json.inputs.length === args.length;
            })[0] || {};

            if (!constructorAbi.payable) {
                throw new Error('Cannot send value to non-payable constructor');
            }
        }

        var bytes = encodeConstructorParams(this.abi, args);
        options.data += bytes;

        if (callback) {

            // wait for the contract address and check if the code was deployed
            this.eth.sendTransaction(options, function (err, hash) {
                if (err) {
                    callback(err);
                } else {
                    // add the transaction hash
                    contract.transactionHash = hash;

                    // call callback for the first time
                    callback(null, contract);

View on GitHub (pinned to 6bb0588ad8)

Solutions

  1. Use the callback form: f.get(function(err, logs) { ... }).
  2. Or wait for filter creation to finish before calling get() synchronously.
  3. For one-shot history, prefer eth.getPastLogs / getLogs-style APIs which are callback/Promise based.

Example fix

// before
var f = eth.filter({fromBlock: 0, toBlock: 'latest'});
var logs = f.get(); // throws when filterId is null

// after
var f = eth.filter({fromBlock: 0, toBlock: 'latest'});
f.get(function (err, logs) { console.log(logs); });
Defensive patterns

Strategy: validation

Validate before calling

function getFilterLogsSync(f) {
  if (f.filterId === null || f.filterId === undefined) {
    throw new Error('filter not yet created; use f.get(callback)');
  }
  return f.get();
}

Type guard

function isFilterReady(f) { return f && f.filterId !== null && f.filterId !== undefined; }

Prevention

When it happens

Trigger: Calling web3.eth.filter({...}).get() immediately in the console (or without new) so get() runs before the filter creation callback has assigned filterId. Typical in the geth console one-liner: var f = eth.filter('latest'); f.get(); fired too early.

Common situations: Interactive geth console usage where the user expects synchronous semantics, or scripts that ignore the async nature of filter creation in the bundled web3 version.

Related errors


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