[SERVER-30649] Check whether each expression inside of $elemMatch is compatible with a given index Created: 14/Aug/17  Updated: 30/Oct/23  Resolved: 07/Sep/17

Status: Closed
Project: Core Server
Component/s: None
Affects Version/s: 3.0.0
Fix Version/s: 3.4.11, 3.5.13

Type: Bug Priority: Major - P3
Reporter: Kimberly Hou Assignee: Nicholas Zolnierz
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Backports
Depends
Backwards Compatibility: Fully Compatible
Operating System: ALL
Backport Requested:
v3.4, v3.2, v3.0
Steps To Reproduce:
Sprint: Query 2017-09-11
Participants:

 Description   

When running certain aggregation operations, it's possible to hit the following error:

2017-08-14T16:16:08.382-0400 F -        [conn1] Invariant failure !index.sparse src/mongo/db/query/index_bounds_builder.cpp 306
2017-08-14T16:16:08.382-0400 F -        [conn1] 
***aborting after invariant() failure
2017-08-14T16:16:08.401-0400 F -        [conn1] Got signal: 6 (Abort trap: 6).



 Comments   
Comment by Githook User [ 30/Oct/17 ]

Author:

{'email': 'nicholas.zolnierz@mongodb.com', 'name': 'Nick Zolnierz', 'username': 'nzolnierzmdb'}

Message: SERVER-30649: Check whether each expression inside of $elemMatch is compatible with a given index

(cherry picked from commit 625d3c1b287170390622055fb29bda7ee12e7b67)
Branch: v3.4
https://github.com/mongodb/mongo/commit/4cdddabcac5393182d4ac64784275631695eece3

Comment by Ramon Fernandez Marina [ 07/Sep/17 ]

Author:

{'username': u'nzolnierzmdb', 'name': u'Nick Zolnierz', 'email': u'nicholas.zolnierz@mongodb.com'}

Message:SERVER-30649: Check whether each expression inside of $elemMatch is compatible with a given index
Branch:master
https://github.com/mongodb/mongo/commit/625d3c1b287170390622055fb29bda7ee12e7b67

Comment by Kimberly Hou [ 14/Aug/17 ]

Backtrace below:

  /data/mci/f8c8042244476c7ab4ae2fe2660ed982/src/src/mongo/util/assert_util.cpp:154:5: mongo::invariantFailed(char const*, char const*, unsigned int)
 /data/mci/f8c8042244476c7ab4ae2fe2660ed982/src/src/mongo/db/query/index_bounds_builder.cpp:306:13: mongo::IndexBoundsBuilder::translate(mongo::MatchExpression const*, mongo::BSONElement const&, mongo::IndexEntry const&, mongo::OrderedIntervalList*, mongo::IndexBoundsBuilder::BoundsTightness*)
 /data/mci/f8c8042244476c7ab4ae2fe2660ed982/src/src/mongo/db/query/index_bounds_builder.cpp:275:9: mongo::IndexBoundsBuilder::translate(mongo::MatchExpression const*, mongo::BSONElement const&, mongo::IndexEntry const&, mongo::OrderedIntervalList*, mongo::IndexBoundsBuilder::BoundsTightness*)
 /data/mci/f8c8042244476c7ab4ae2fe2660ed982/src/src/mongo/db/query/planner_access.cpp:248:9: mongo::QueryPlannerAccess::makeLeafNode(mongo::CanonicalQuery const&, mongo::IndexEntry const&, unsigned long, mongo::MatchExpression*, mongo::IndexBoundsBuilder::BoundsTightness*)
 /data/mci/f8c8042244476c7ab4ae2fe2660ed982/src/src/mongo/db/query/planner_access.cpp:1192:24: mongo::QueryPlannerAccess::buildIndexedDataAccess(mongo::CanonicalQuery const&, mongo::MatchExpression*, bool, std::__1::vector<mongo::IndexEntry, std::__1::allocator<mongo::IndexEntry> > const&, mongo::QueryPlannerParams const&)
 /data/mci/f8c8042244476c7ab4ae2fe2660ed982/src/src/mongo/db/query/query_planner.cpp:859:57: mongo::QueryPlanner::plan(mongo::CanonicalQuery const&, mongo::QueryPlannerParams const&, std::__1::vector<mongo::QuerySolution*, std::__1::allocator<mongo::QuerySolution*> >*)
 /data/mci/f8c8042244476c7ab4ae2fe2660ed982/src/src/mongo/db/query/get_executor.cpp:384:21: mongo::(anonymous namespace)::prepareExecution(mongo::OperationContext*, mongo::Collection*, mongo::WorkingSet*, std::__1::unique_ptr<mongo::CanonicalQuery, std::__1::default_delete<mongo::CanonicalQuery> >, unsigned long)
 /data/mci/f8c8042244476c7ab4ae2fe2660ed982/src/src/mongo/db/query/get_executor.cpp:475:9: mongo::getExecutor(mongo::OperationContext*, mongo::Collection*, std::__1::unique_ptr<mongo::CanonicalQuery, std::__1::default_delete<mongo::CanonicalQuery> >, mongo::PlanExecutor::YieldPolicy, unsigned long)
 /data/mci/f8c8042244476c7ab4ae2fe2660ed982/src/src/mongo/db/pipeline/pipeline_d.cpp:435:12: mongo::(anonymous namespace)::attemptToGetExecutor(mongo::OperationContext*, mongo::Collection*, mongo::NamespaceString const&, boost::intrusive_ptr<mongo::ExpressionContext> const&, mongo::BSONObj, mongo::BSONObj, mongo::BSONObj, mongo::AggregationRequest const*, unsigned long)
 /data/mci/f8c8042244476c7ab4ae2fe2660ed982/src/src/mongo/db/pipeline/pipeline_d.cpp:673:27: mongo::PipelineD::prepareExecutor(mongo::OperationContext*, mongo::Collection*, mongo::NamespaceString const&, mongo::Pipeline*, boost::intrusive_ptr<mongo::ExpressionContext> const&, boost::intrusive_ptr<mongo::DocumentSourceSort> const&, mongo::DepsTracker const&, mongo::BSONObj const&, mongo::AggregationRequest const*, mongo::BSONObj*, mongo::BSONObj*)
 /data/mci/f8c8042244476c7ab4ae2fe2660ed982/src/src/mongo/db/pipeline/pipeline_d.cpp:531:17: mongo::PipelineD::prepareCursorSource(mongo::Collection*, mongo::NamespaceString const&, mongo::AggregationRequest const*, mongo::Pipeline*)
 /data/mci/f8c8042244476c7ab4ae2fe2660ed982/src/src/mongo/db/commands/run_aggregate.cpp:440:9: mongo::runAggregate(mongo::OperationContext*, mongo::NamespaceString const&, mongo::AggregationRequest const&, mongo::BSONObj const&, mongo::BSONObjBuilder&)
 /data/mci/f8c8042244476c7ab4ae2fe2660ed982/src/src/mongo/db/commands/pipeline_command.cpp:91:36: mongo::(anonymous namespace)::PipelineCommand::run(mongo::OperationContext*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, mongo::BSONObj const&, mongo::BSONObjBuilder&)
 /data/mci/f8c8042244476c7ab4ae2fe2660ed982/src/src/mongo/db/commands.cpp:376:12: mongo::BasicCommand::enhancedRun(mongo::OperationContext*, mongo::OpMsgRequest const&, mongo::BSONObjBuilder&)
 /data/mci/f8c8042244476c7ab4ae2fe2660ed982/src/src/mongo/db/service_entry_point_mongod.cpp:451:27: mongo::(anonymous namespace)::runCommandImpl(mongo::OperationContext*, mongo::Command*, mongo::OpMsgRequest const&, mongo::rpc::ReplyBuilderInterface*, mongo::LogicalTime)
 /data/mci/f8c8042244476c7ab4ae2fe2660ed982/src/src/mongo/db/service_entry_point_mongod.cpp:692:0: mongo::(anonymous namespace)::execCommandDatabase(mongo::OperationContext*, mongo::Command*, mongo::OpMsgRequest const&, mongo::rpc::ReplyBuilderInterface*)
 /data/mci/f8c8042244476c7ab4ae2fe2660ed982/src/src/mongo/db/service_entry_point_mongod.cpp:799:9: mongo::(anonymous namespace)::runCommands(mongo::OperationContext*, mongo::Message const&)
 /data/mci/f8c8042244476c7ab4ae2fe2660ed982/src/src/mongo/db/service_entry_point_mongod.cpp:1066:0: mongo::ServiceEntryPointMongod::handleRequest(mongo::OperationContext*, mongo::Message const&)
 /data/mci/f8c8042244476c7ab4ae2fe2660ed982/src/src/mongo/transport/service_state_machine.cpp:317:35: mongo::ServiceStateMachine::_processMessage(mongo::ServiceStateMachine::ThreadGuard&)
 /data/mci/f8c8042244476c7ab4ae2fe2660ed982/src/src/mongo/transport/service_state_machine.cpp:406:17: mongo::ServiceStateMachine::_runNextInGuard(mongo::ServiceStateMachine::ThreadGuard&)
 /data/mci/f8c8042244476c7ab4ae2fe2660ed982/src/src/mongo/transport/service_state_machine.cpp:372:12: mongo::ServiceStateMachine::runNext()
 /data/mci/f8c8042244476c7ab4ae2fe2660ed982/src/src/mongo/transport/service_entry_point_impl.cpp:89:18: mongo::ServiceEntryPointImpl::startSession(std::__1::shared_ptr<mongo::transport::Session>)::$_1::operator()()

Comment by Charlie Swanson [ 14/Aug/17 ]

Thanks Kimberly!

Can you post the backtrace? I'll paste the line snippet you sent me earlier, for reference:

src/mongo/db/query/index_bounds_builder.cpp:306

        // If we have a NOT -> EXISTS, we must handle separately.
        if (MatchExpression::EXISTS == child->matchType()) {
            // We should never try to use a sparse index for $exists:false.
            invariant(!index.sparse);
            BSONObjBuilder bob;
            bob.appendNull("");
            bob.appendNull("");
            BSONObj dataObj = bob.obj();
            oilOut->intervals.push_back(
                makeRangeInterval(dataObj, BoundInclusion::kIncludeBothStartAndEndKeys));
 
            *tightnessOut = IndexBoundsBuilder::INEXACT_FETCH;
            return;
        }

Generated at Thu Feb 08 04:24:33 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.