This code:

    $result = db_query("SELECT p.perm FROM {role} r INNER JOIN {permission} p ON p.rid = r.rid WHERE r.rid IN (". db_placeholders($account->roles) .")", array_keys($account->roles));

will throw errors if $account->roles is not an array yet there is no test to verify that it is an array before running the query.

The errors will be similar to:

warning: array_fill() [function.array-fill]: Number of elements must be positive in /var/www/html/drupal/includes/database.inc on line 253.
warning: implode() [function.implode]: Invalid arguments passed in /var/www/html/drupal/includes/database.inc on line 253.
warning: array_keys() [function.array-keys]: The first argument should be an array in /var/www/html/drupal/modules/user/user.module on line 502.
user warning: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1 query: SELECT p.perm FROM role r INNER JOIN permission p ON p.rid = r.rid WHERE r.rid IN () in /var/www/html/drupal/modules/user/user.module on line 502.

One solution would be to test $account->roles before running the query:

  if (!isset($perm[$account->uid]) && isset($account->roles)) {
    $result = db_query("SELECT p.perm FROM {role} r INNER JOIN {permission} p ON p.rid = r.rid WHERE r.rid IN (". db_placeholders($account->roles) .")", array_keys($account->roles));

Another solution would be to set $account->roles in the event that it's not set:

  if (!isset($perm[$account->uid])) {
    if (!isset($account->roles)) {
      $account->roles[1] = 'anonymous user';
    }
    $result = db_query("SELECT p.perm FROM {role} r INNER JOIN {permission} p ON p.rid = r.rid WHERE r.rid IN (". db_placeholders($account->roles) .")", array_keys($account->roles));

Either solution eliminates the warnings. Not sure which (if either) is preferable.

Comments

najibx’s picture

i'm bumping into this same error when running drush. would it be in drush issue?
"The problem with both this and the other issue may be that the Anonymous user is not in the database. Since there is no anonymous user in the database (in the "users" table) the user information can never be loaded." similar to http://drupal.org/node/377396

pneumatic’s picture

Thanks - your first solution fixed my problem which was that the NTLM single sign on would trigger this error because it was checking permissions before the account was created. I am posting my error log so that others can search for this solution.

warning: array_fill() [function.array-fill]: Number of elements must be positive in /var/www/includes/database.inc on line 253. 

warning: implode() [function.implode]: Invalid arguments passed in /var/www/includes/database.inc on line 253. 

warning: array_keys() [function.array-keys]: The first argument should be an array in /var/www/modules/user/user.module on line 513. 

user warning: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1 query: SELECT p.perm FROM role r INNER JOIN permission p ON p.rid = r.rid WHERE r.rid IN () in /var/www/modules/user/user.module on line 513. 
danzsmith’s picture

First of all - thanks very much for this! This solution really helped me in a bind...

Secondly, I can now tell you from experience, the second solution, this one:

<?php
  if (!isset($perm[$account->uid])) {
    if (!isset($account->roles)) {
      $account->roles[1] = 'anonymous user';
    }
    $result = db_query("SELECT p.perm FROM {role} r INNER JOIN {permission} p ON p.rid = r.rid WHERE r.rid IN (". db_placeholders($account->roles) .")", array_keys($account->roles));
?>

was prefereable in my scenario. I was using a combination of the webserver_authentication and user_selectable_roles modules and the first solution gave me a white screen with no way to log back in whereas the second solution, dictated above, worked perfectly.

Just wanted to pass that on to everyone...

Thanks again!

mikeytown2’s picture

Title: "Number of elements must be positive in ..." error » Empty $account->roles causes a sql error in user_access
Version: 6.14 » 6.x-dev
Category: support » bug
Status: Active » Needs review
StatusFileSize
new902 bytes

http://api.drupal.org/api/function/user_access/6

Because $account is an object assigning it the role of "anonymous user" is not a good idea. Objects are passed by reference so this change will propagate back.

hymanroth’s picture

If a user object has no roles then it can't have permissions, right?

So I added one line:

if (!isset($perm[$account->uid])) {
    
    if (empty($account->roles)) {
      return FALSE;
    }
    
    $result = db_query("SELECT p.perm FROM {role} r INNER JOIN {permission} p ON p.rid = r.rid WHERE r.rid IN (". db_placeholders($account->roles) .")", array_keys($account->roles));

    $perms = array();
    while ($row = db_fetch_object($result)) {
      $perms += array_flip(explode(', ', $row->perm));
    }
    $perm[$account->uid] = $perms;
  }

The key thing is not to touch $account or $perm.
If user_access is called again on the same account, but this time with ->roles populated, then the function will still work normally.

j0nathan’s picture

Same error messages. Subscribing.

verta’s picture

I am getting this as user 1, on creating a new page. I am testing several modules, so I can't tell yet which one started this, but I am using PHP 5.3.

Page new page has been created.

# warning: array_fill() [function.array-fill]: Number of elements must be positive in includes\database.inc on line 253.

# warning: implode() [function.implode]: Invalid arguments passed in includes\database.inc on line 253.

# warning: array_keys() expects parameter 1 to be array, null given in modules\user\user.module on line 513.

# user warning: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1 query: SELECT p.perm FROM role r INNER JOIN permission p ON p.rid = r.rid WHERE r.rid IN () in modules\user\user.module on line 513.

Edit: turns out cron had not run after enabling Actions. No more error messages.

ppc.coder’s picture

I was experiencing a similiar problem.

In my case, the problem was for my menu, I passed in 2 permissions like so:

'access arguments' => array('perm1', 'perm2')

What then happens is that in the user_access function

'perm1' is picked up as the permission to test for and 'perm2' is picked up as the $account argument!

qmhao99’s picture

I was having the same problem. It appears that the problem went away after I inserted a row in users table with uid=0 and name=anonymous.

Status: Needs review » Needs work

The last submitted patch, drupal-777116.patch, failed testing.

chissy’s picture

Same problem. Occurred when I deleted some users before deleting the content they had created, resulted because anonymous users can't create content. Second solution eliminated the error message but I still have spaces on the page that say "n/a" where the content created by the deleted users would have been, anyone know of a way to get rid of this?

HydroZ’s picture

Hi to all,

please check this post, for my solution, that is possibly fitting to your situations:

http://drupal.org/node/988216

HydroZ’s picture

Hi to all,

please check this post, for my solution, that is possibly fitting to your situations:

http://drupal.org/node/988216

mikedotexe’s picture

the
&& isset($account->roles)

part was the only piece missing from my user.module. I added that and it works.
You just saved my hindquarters. Thank you.

anarcat’s picture

Status: Needs work » Needs review
StatusFileSize
new533 bytes

While I believe that this is a data corruption issue that should be resolved in those specific installs, it doesn't hurt to not *crash* over the wrong data. "Be tolerant in what you receive and conservative in what you send."

I rerolled the patch to have the right suffix and to make sure we actually deny access to those evil corrupted users.

Maybe a warning should be in order here?

anarcat’s picture

Version: 6.x-dev » 7.x-dev
StatusFileSize
new559 bytes

Note that this also applies to Drupal 7, another patch applied just for this, which should apply on 7.x...

droplet’s picture

Version: 7.x-dev » 8.x-dev
droplet’s picture

#16: 777116-no-roles-error.patch queued for re-testing.

rasskull’s picture

#15 worked great for me an solved a big problem we were having, thanks!

SchwebDesign’s picture

Thanks a million for this patch #15. that worked for me as well. This issue was very hard to debug on my site and this post was a HUGE help, thanks everyone.

fugazi’s picture

patch # 15 works well for me many thanks to Drupal 6

anarcat’s picture

Status: Needs review » Reviewed & tested by the community
xjm’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs tests, +Novice

Thanks for the patch!

It looks like #16 won't apply to Drupal 8. Also, I think we should add an automated test for this.

Tagging as novice to reroll for D8 and add an automated test.

emclaughlin’s picture

StatusFileSize
new579 bytes

Here's a reroll at least. If I figure out how to add an automated test I'll come back and do that, but fair game for now.

xjm’s picture

Status: Needs work » Needs review

Thanks @emclaughlin! Setting to Needs Review so that the bot tests it.

xjm’s picture

Status: Needs review » Needs work

Alright, back to NW for an automated test.

oriol_e9g’s picture

StatusFileSize
new941 bytes
new1.49 KB

Test added.

oriol_e9g’s picture

Status: Needs work » Needs review
xjm’s picture

Issue tags: -Needs tests, -Novice

Thanks @oriol_e9g! Sending to testbot.

Status: Needs review » Needs work

The last submitted patch, no-roles-onlytests-777116-28.patch, failed testing.

xjm’s picture

Status: Needs work » Needs review

Cool, the test-only patch fails and the combined patch passes, as expected.

virtuali1151’s picture

# 15 fixed my error as well... TK U!!!

oriol_e9g’s picture

Status: Needs review » Reviewed & tested by the community

@virtuali1151 Reviewed & tested by the community?

oriol_e9g’s picture

Status: Reviewed & tested by the community » Needs review

crosspost :/

virtuali1151’s picture

Shouldnt this be commited core..? Just ran across the same prob again when upgrading to 6.25.....

xjm’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: +Needs backport to D6, +Needs backport to D7

@virtuali1151, the patch needs to be reviewed before it can be committed.

I've gone back and forth over whether this patch is babysitting broken code. In the end, I think $account->roles being set as an empty array is actually the correct behavior for a "roleless" user (whatever that means), so we should respond to that sensibly. The fix is also nice and clean.

catch’s picture

Status: Reviewed & tested by the community » Needs work

I'm not sure about this at all. As far as I know there's no valid situation where a user has no roles at all - since every user has either the authenticated or anonymous role which are hard-coded. There are no links to bugs in the contrib modules that are hitting this error from this issue, and the patch means that they'll just fail silently rather than throwing a useful error message, meaning there's no incentive at all to track down the actual cause of the problem once this goes in.

xjm’s picture

So I guess then the solution is instead to try to determine which users are missing roles, and what code (probably a contributed module) is creating or altering them?

Dthorndyke’s picture

At last! A solution to my issues! Thank you tons ppc.coder : )

Specifying only a single permission to access arguments cleared up these error messages as well as properly displaying my module tabs, which I had spent considerable time looking into.

Just wanted to second this solution to the problem for any other weary souls that haven't found a suitable solution for their situation.

'access arguments' => array('perm1')

Worked for me!

James Marks’s picture

(Comment #9 by qmhao99) I was having the same problem. It appears that the problem went away after I inserted a row in users table with uid=0 and name=anonymous.

HydroZephalus (Comment #12) found the same thing: http://drupal.org/node/988216

(Comment #37 by catch regarding the patch) I'm not sure about this at all. As far as I know there's no valid situation where a user has no roles at all - since every user has either the authenticated or anonymous role which are hard-coded.

Are these errors related to/caused by the situation where UID 0 is missing from the users table? (http://drupal.org/node/1029506, http://drupal.org/node/204411)

emclaughlin’s picture

Yes, they appear to be.

ailgm’s picture

I'm hitting these errors (in D6.26) and do have UID 0 in the users table. There is no row for that user in the users_roles table, but that appears to be normal.

kenorb’s picture

I've the same errors in Pressflow 6.22 while running simpletests.

array_fill() [function.array-fill]: Number of elements must be positive
implode() [function.implode]: Invalid arguments passed
array_keys() expects parameter 1 to be array, null given
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1 query: SELECT p.perm FROM simpletest775107role r INNER JOIN simpletest775107permission p ON p.rid = r.rid WHERE r.rid IN ()

The following code:

    $result = db_query("SELECT p.perm FROM {role} r INNER JOIN {permission} p ON p.rid = r.rid WHERE r.rid IN (". db_placeholders($account->roles) .")", array_keys($account->roles));

expects that user has always some role.

Please backport it into 6.x as well.

kenorb’s picture

After debugging, my case was related to simpletest_clone module.
So simply my table didn't have UID = 0 and 1. Also global $user variable was NULL.
Link: #1784638: Simpletest: User created with errors (array_fill, implode, array_keys, SQL error)

If any of you have this error, make sure that:
- you have user with UID = 0 in your users table (sometimes it's removed by some weird modules containing bugs),
- you have user with UID = 1 in your users table,
- before calling user_access(), make sure that your global $user is not empty or overriden by some other code,

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

dpi’s picture

Status: Needs work » Closed (won't fix)

will throw errors if $account->roles is not an array yet there is no test to verify that it is an array before running the query.

This will no longer happen in D8 since $user->getRoles() is guaranteed to return an array.

The problematic query no longer exists in D7, and it also appears that role is always an array in D7, and it is prepopulated with authenticated or anonymous roles (See \UserController::attachLoad)