phalcon/cphalcon · error · Phalcon\Tag\Exception

Resultset returned an invalid value

Error message

Resultset returned an invalid value

What it means

While generating options from a resultset, Tag\Select::optionsFromResultset() iterates every row and reads the two 'using' fields. Each row must be an object (model or stdClass, optionally with readAttribute()) or an array. A row that is a scalar (string, int, null) cannot yield value/text, so rendering aborts with Phalcon\Tag\Exception 'Resultset returned an invalid value' (phalcon/Tag/Select.zep:283).

Source

Thrown at phalcon/Tag/Select.zep:283

            let usingZero = self::toStringValue(using[0]),
                usingOne  = self::toStringValue(using[1]);
        }

        let escaper = <EscaperInterface> BaseTag::getEscaperService();

        for option in iterator(resultset) {
            if typeof using == "array" {
                if typeof option == "object" {
                    if method_exists(option, "readAttribute") {
                        let optionValue = option->readAttribute(usingZero);
                        let optionText = option->readAttribute(usingOne);
                    } else {
                        let optionValue = option->{usingZero};
                        let optionText = option->{usingOne};
                    }
                } else {
                    if unlikely typeof option != "array" {
                        throw new Exception(
                            "Resultset returned an invalid value"
                        );
                    }

                    let optionValue = option[usingZero];
                    let optionText = option[usingOne];
                }

                let optionValue = escaper->attributes(self::toStringValue(optionValue));
                let optionText = escaper->html(self::toStringValue(optionText));

                /**
                 * If the value is equal to the option's value we mark it as
                 * selected
                 */
                if typeof value == "array" {
                    if in_array(optionValue, value) {
                        let code .= self::echoOption(optionValue, true)

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Pass the original resultset of model objects (or array rows), not a flattened/mapped scalar list.
  2. Map rows to value=>text pairs and render with Tag::selectStatic(['city'], $options).
  3. If rows are arrays, ensure each row contains both 'using' keys; if objects, ensure the two properties are readable.

Example fix

// before
$cities = array_column($repo->all()->toArray(), 'name'); // flat list of strings
Tag::select(['city', $cities, 'using' => ['id', 'name']]); // throws

// after
$options = [];
foreach ($repo->all() as $row) {
    $options[$row->id] = $row->name;
}
Tag::selectStatic(['city'], $options);
Defensive patterns

Strategy: validation

Validate before calling

$rows = is_array($data) ? $data : iterator_to_array($data);
foreach ($rows as $row) {
    if (!is_array($row) && !is_object($row)) {
        throw new InvalidArgumentException('Select data rows must be arrays or objects');
    }
}

Type guard

/** @param iterable<array|object> $data */
function assertSelectData(iterable $data): void
{
    foreach ($data as $row) {
        if (!is_array($row) && !is_object($row)) {
            throw new TypeError('Select data must contain rows, not scalars');
        }
    }
}

Try / catch

try {
    echo Tag::select(['city', $resultset, 'using' => ['id', 'name']]);
} catch (\Phalcon\Tag\Exception $e) {
    $logger->warning('Falling back to empty select: ' . $e->getMessage());
    echo '<select name="city"></select>';
}

Prevention

When it happens

Trigger: Passing a Traversable/ResultsetInterface whose iterator() yields scalars: a generator that maps rows to strings, a custom resultset of single values, a cached/serialized resultset whose rows became scalars, or an iterable of nulls.

Common situations: Selecting a single column and mapping it to a flat list before feeding Tag::select; wrapping a resultset in a caching layer that flattens rows; array_column() output passed as data with a resultset-typed option; hydration modes that produce scalars.

Related errors


AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21). Data as JSON: /api/errors/d839bf308202ffaf. Report an issue: GitHub.