Unsupported operand types in factory_by_row() in flag_flag.inc

Created on 24 February 2013, over 12 years ago
Updated 19 August 2025, 6 days ago

Problem/Motivation

The current implementation of the flags module integration with the rules module can lead to a fatal error under certain situtations. The source of the fatal error is a bad operand to the array_merge function.

The behavior of array_merge() was modified in PHP 5. Unlike PHP 4, array_merge() now only accepts parameters of type array. However, you can use typecasting to merge other types.

One pathway to this error situation is when the module_implements variable becomes incomplete, possibly due to a bad cache flush under heavy load. In these situations sites will stop working properly, but should still bootstrap completely enough to correct the corrupted cache. Under this type of condition, the flag module doesn't do adequate sanity checks leading to the fatal error and incomplete bootstrap. Additional information on cache poisoning can be found in another thread: https://www.drupal.org/node/1934192#comment-7363318

When it tries to load all of the defined flags, it is expecting that it will always get at least the default link types. The issue we are seeing is being caused by flag_get_link_types() returning an empty array. In the corrupted cache situation, the flag.flag.inc file may not get loaded so the hook with the default link types is not run. Since the default link types are loaded via the flag_link_type_info hook, and then modified by the flag_link_type_info alter hook, the Flag module could also get any combination of results due to other poorly written modules. As a result, the $flag->get_link_type() method can return something other than an array (ie. NULL).

Specifically, when the $flag->options() method is called it does the following:

<?php
    // Merge in options from the current link type.
    $link_type = $this->get_link_type();
    $options = array_merge($options, $link_type['options']);
?>

Having a rule defined is not a requirement for this bug to appear, but having a flag defined is. The Flag module tries to interrate over all defined flags to expose them as events to Rules. The problem is simply assuming that the values being assigned both exist and are an array, which, while it's supposed to exist and supposed to be an array, can not simply be expected 100% of the time in a contributed, alterable ecosystem.

Proposed resolution

The code is already typecasting the $options variable.

$flag_options = (array) $flag->options();

Why not the same for the flag options?

$link_type = (array) $this->get_link_type();

That at least guarantees that when you do a += or array_merge, the values are empty arrays. The argument really isn't that they should never be empty, the argument is handling it better than a fatal error that kills the bootstrap process.

The fact is that in certain edge cases, the options are NULL or empty, which does not play well with += assignment of another type. Typecasting just ensures your data type is what you expect.

Remaining tasks

Once something like a simple typecasting casting is added to the code, nothing else needs to happen. All functionality will remain the same. It just removes a potential fatal error condition.

User interface changes

None.

API changes

None.

Original report by vinoth.3v

I am getting Fatal error: Unsupported operand types in flag/includes/flag/flag_flag.inc on line 130

Drupal 7.20
Flag 7.x-3.x-dev and 7.x-3.0-alpha4

any Idea?

🐛 Bug report
Status

Closed: outdated

Version

3.0

Component

Flag core

Created by

🇮🇳India vinoth.3v

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.71.5 2024