{"record":{"id":"ba871ba481d218f4","repo":"cube-js/cube","slug":"unable-to-convert-map-to-python-object-key-must-b","errorCode":null,"errorMessage":"Unable to convert Map to Python object: key must be string, actual: {}","messagePattern":"Unable to convert Map to Python object: key must be string, actual: (.+?)","errorType":"exception","errorClass":"minijinja::Error","httpStatus":null,"severity":"error","filePath":"packages/cubejs-backend-native/src/template/mj_value/python.rs","lineNumber":83,"sourceCode":"        }\n        mjv::ValueKind::Map => {\n            let mut obj = CLReprObject::new(if from.is_kwargs() {\n                CLReprObjectKind::KWargs\n            } else {\n                CLReprObjectKind::Object\n            });\n\n            for key in from.try_iter()? {\n                let value = if let Ok(v) = from.get_item(&key) {\n                    from_minijinja_value(&v)?\n                } else {\n                    CLRepr::Null\n                };\n\n                let key_str = if let Some(key) = key.as_str() {\n                    key.to_string()\n                } else {\n                    return Err(mj::Error::new(\n                        mj::ErrorKind::InvalidOperation,\n                        format!(\n                            \"Unable to convert Map to Python object: key must be string, actual: {}\",\n                            key.kind()\n                        ),\n                    ));\n                };\n\n                obj.insert(key_str, value);\n            }\n\n            Ok(CLRepr::Object(obj))\n        }\n        other => Err(mj::Error::new(\n            mj::ErrorKind::InvalidOperation,\n            format!(\"Converting from {:?} to Python is not supported\", other),\n        )),\n    }","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-backend-native/src/template/mj_value/python.rs#L65-L101","documentation":"When converting a MiniJinja `Map` to a Python object, every key must be a string. `from_minijinja_value` reads each key and, if `key.as_str()` is `None`, raises this error including the actual key kind. Python object (dict) keys are expected to be strings in this bridge.","triggerScenarios":"A template passes a map with non-string keys (e.g. integer keys like `{1: 'a'}`) into a Python filter, method call, or as a nested value during conversion.","commonSituations":"Building dicts in Jinja with numeric keys from loops (`{i: value}` inside a for loop), JSON objects produced with numeric keys, or merging maps keyed by indices.","solutions":["Convert keys to strings in the template: use `|string` on keys when constructing the map.","Key the map by string loop variables (`loop.index | string`) instead of raw integers.","Restructure the data as a sequence of objects if keys are inherently numeric.","Handle the conversion in Python from a JSON string instead of a map value."],"exampleFix":"// before\n{% set m = {loop.index: item} %}\n// after\n{% set m = {loop.index.__string__(): item} %}  {# or build with string keys #}","handlingStrategy":"validation","validationCode":"// in Jinja, ensure map keys are strings:\n{% set m = {} %}{% for k, v in data %}{% set _ = m.update({k | string: v}) %}{% endfor %}","typeGuard":"fn map_keys_all_strings(v: &serde_json::Map<String, serde_json::Value>) -> bool { true } // enforce at map construction","tryCatchPattern":null,"preventionTips":["Never build maps with numeric keys for Python interop","Use |string on keys derived from loop indices","Represent numeric-keyed data as arrays of objects instead"],"tags":["python","minijinja","type-conversion","template"],"backgroundTag":"unsupported-type-conversion","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}