Error in GAE with ndb - BadQueryError: Cannot convert FalseNode to predicate
Asked Answered
G

2

14

I have an application running on Google App Engine with python. Model classes extend from ndb (google.appengine.ext.ndb) classes.

One of my views makes async calls to the database, something more or less like:

# ExerciseListLog is a ndb model class
# start_current, end_current are dates
# student_id is a string
# contents is a list of keys

exercise_log_query = ExerciseListLog.query(ndb.AND(ExerciseListLog.creation >= start_current,
    ExerciseListLog.creation < end_current,
    ExerciseListLog.user_id == student_id))
exercise_log_query = exercise_log_query.filter(ExerciseListLog.content.IN(contents))

future = exercise_log_query.count_async()

count = future.get_result() # this throws BadQueryError

this is throwing an error on get_result(): BadQueryError: Cannot convert FalseNode to predicate

But it only happens when I deploy my code to the Google cloud. When I run it locally it works fine.

I have no idea what this error means and looking it up on Google is not helping much. Anyone knows what's wrong here?

Here's the full stacktrace from GAE's logs

Traceback (most recent call last):
  File "/base/data/home/apps/s~qmagtest/1.366092357976105290/zen/web/gae/convention.py", line 48, in make_convention
    method(*args, **kwargs)
  File "/base/data/home/apps/s~qmagtest/1.366092357976105290/core/web/qmhandler.py", line 48, in wrapper
    return method(self, *args, **kwargs)
  File "/base/data/home/apps/s~qmagtest/1.366092357976105290/core/user/login/security.py", line 36, in wrapper
    method(self, *args, **kwargs)
  File "/base/data/home/apps/s~qmagtest/1.366092357976105290/core/user/security.py", line 17, in wrapper
    method(self, *args_inner, **kwargs)
  File "/base/data/home/apps/s~qmagtest/1.366092357976105290/plugins/web/desempenho/estatisticas.py", line 127, in class_activities
    school_class.content)
  File "/base/data/home/apps/s~qmagtest/1.366092357976105290/plugins/web/desempenho/estatisticas.py", line 178, in _get_exercise_video_and_total_weekly_series
    exercise_log_count = exercise_count_futures[i].get_result()
  File "/python27_runtime/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 325, in get_result
    self.check_success()
  File "/python27_runtime/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 371, in _help_tasklet_along
    value = gen.send(val)
  File "/python27_runtime/python27_lib/versions/1/google/appengine/ext/ndb/query.py", line 1227, in _count_async
    dsquery = self._get_query(conn)
  File "/python27_runtime/python27_lib/versions/1/google/appengine/ext/ndb/query.py", line 873, in _get_query
    filters = filters._to_filter()
  File "/python27_runtime/python27_lib/versions/1/google/appengine/ext/ndb/query.py", line 599, in _to_filter
    for node in self.__nodes
  File "/python27_runtime/python27_lib/versions/1/google/appengine/ext/ndb/query.py", line 600, in <genexpr>
    if isinstance(node, PostFilterNode) == post))
  File "/python27_runtime/python27_lib/versions/1/google/appengine/ext/ndb/query.py", line 425, in _to_filter
    'Cannot convert FalseNode to predicate')
BadQueryError: Cannot convert FalseNode to predicate
Gaffney answered 20/3, 2013 at 18:7 Comment(0)
L
25

I suspect the problem is that contents is an empty list. That is pretty much the only reason FalseNode could ever appear. (The other is calling AND() without arguments.) Your observation that removing this line corroborates my hunch. You probably didn't expect this to happen, and in your local tests it never happened... You probably need to debug the code that comes up with that list.

I agree that the error message could be better.

Leathern answered 21/3, 2013 at 16:22 Comment(2)
You might be right. I'll test your assumption and post back. Thanks!Breunig
Guido, you were right. I can use content.IN in this case as long as contents is not empty. Thanks!!Breunig
G
1

Update:

I found out that if I remove the line:

exercise_log_query = exercise_log_query.filter(ExerciseListLog.content.IN(contents))

Then it will work.

So, the error has nothing to do with the async call to the database. It happens because Google AppEngine supports inequality filters in only one field per query. Apparently using "content.IN" counts as a second inequality, which is not allowed.

That error message could be better.


UPDATE:

It turns out Guido is right, and my explanation above is WRONG. content.IN is working now that contents is not empty.

Gaffney answered 20/3, 2013 at 19:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.