{"record":{"id":"7ffa369bb0c3cc1e","repo":"getredash/redash","slug":"oids-takes-an-array-as-input","errorCode":null,"errorMessage":"$oids takes an array as input.","messagePattern":"\\$oids takes an array as input\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"redash/query_runner/mongodb.py","lineNumber":50,"sourceCode":"    enabled = False\n\n\nTYPES_MAP = {\n    str: TYPE_STRING,\n    bytes: TYPE_STRING,\n    int: TYPE_INTEGER,\n    float: TYPE_FLOAT,\n    bool: TYPE_BOOLEAN,\n    datetime.datetime: TYPE_DATETIME,\n}\n\n\ndate_regex = re.compile(r'ISODate\\(\"(.*)\"\\)', re.IGNORECASE)\n\n\ndef parse_oids(oids):\n    if not isinstance(oids, list):\n        raise Exception(\"$oids takes an array as input.\")\n\n    return [bson_object_hook({\"$oid\": oid}) for oid in oids]\n\n\ndef datetime_parser(dct):\n    for k, v in dct.items():\n        if isinstance(v, str):\n            m = date_regex.findall(v)\n            if len(m) > 0:\n                dct[k] = parse(m[0], yearfirst=True)\n\n    if \"$humanTime\" in dct:\n        return parse_human_time(dct[\"$humanTime\"])\n\n    if \"$oids\" in dct:\n        return parse_oids(dct[\"$oids\"])\n\n    opts = JSONOptions(tz_aware=True)","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/getredash/redash/blob/ca79fe988d81cdac9675b412f3dfcab107bc1fbc/redash/query_runner/mongodb.py#L32-L68","documentation":"parse_oids() is used by the MongoDB query runner's JSON deserializer to expand \"$oid\" constructs in queries (writing ObjectIds as JSON). It requires its input to be a JSON array of ObjectId hex strings; anything else is rejected. This is the error path for {\"$oid\": ...}-style documents built incorrectly.","triggerScenarios":"A query contains {\"$oid\": {\"$oids\": \"5f1a...\"}} or passes an object/string where an array is expected, e.g. \"$oids\": {\"0\": \"abc\"} instead of \"$oids\": [\"abc\"].","commonSituations":"Converting an ObjectId to JSON with a custom encoder that emits $oid/$oids but wrapping multiple ids in a dict instead of a list; hand-writing extended JSON that doesn't follow the array shape.","solutions":["Ensure the $oids value is a JSON array: {\"$oid\": {\"$oids\": [\"hex1\", \"hex2\"]}}","For a single ObjectId use {\"$oid\": \"<24-char hex>\"} directly instead of $oids","Regenerate the extended JSON with a proper bson/json_util serializer"],"exampleFix":"// before\n{\"_id\": {\"$oid\": {\"$oids\": \"507f1f77bcf86cd799439011\"}}}\n// after\n{\"_id\": {\"$oid\": \"507f1f77bcf86cd799439011\"}}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"def as_oid_array(v):\n    assert isinstance(v, list) and all(isinstance(o, str) and len(o) == 24 for o in v), 'oids must be array of 24-hex strings'\n    return v","tryCatchPattern":"try:\n    run_mongodb_query(q)\nexcept Exception as e:\n    if '$oids takes an array' in str(e):\n        q = fix_extended_json_oids(q)  # wrap ids in a list, use $oid for single id","preventionTips":["Use bson.json_util to serialize ObjectIds instead of hand-writing $oid/$oids","Single id: {\"$oid\": hex}; multiple: {\"$oids\": [hex, ...]}"],"tags":["mongodb","redash","extended-json","objectid"],"backgroundTag":"extended-json-parse-error","analyzedSha":"ca79fe988d81cdac9675b412f3dfcab107bc1fbc","analyzedAt":"2026-08-28T18:32:34.637Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}