{"record":{"id":"7e36dd2fe465c1e6","repo":"apple/pkl","slug":"cannotrenderprotobufmapkey","errorCode":"cannotRenderProtobufMapKey","errorMessage":"cannotRenderProtobufMapKey","messagePattern":"cannotRenderProtobufMapKey","errorType":"error_code","errorClass":"VmException","httpStatus":null,"severity":"error","filePath":"pkl-core/src/main/java/org/pkl/core/stdlib/protobuf/RendererNodes.java","lineNumber":313,"sourceCode":"      visit(value);\n      var popped = wrapperRequirement.pop();\n      assert popped : \"Corrupted traversal stack.\";\n      if (addedType) {\n        propertyPath.pop();\n        endMessage();\n      }\n      if (requiresWrapper()) {\n        propertyPath.pop();\n      }\n    }\n\n    @Override\n    protected void visitEntryKey(Object key, boolean isFirst) {\n      var isDirective = isRenderDirective(key);\n      var isValidKey =\n          isDirective || key instanceof Long || key instanceof Boolean || key instanceof String;\n      if (!isValidKey) {\n        throw new VmExceptionBuilder()\n            .evalError(\"cannotRenderProtobufMapKey\")\n            .withProgramValue(\"Key\", key)\n            .build();\n      }\n      writePropertyName();\n      startMessage();\n      startNewLine();\n      builder.append(\"key: \");\n      if (isDirective) {\n        builder.append(VmUtils.readTextProperty(key));\n      } else if (key instanceof String string) {\n        builder.append('\"').append(jsonEscaper.escape(string)).append('\"');\n      } else {\n        builder.append(key);\n      }\n    }\n\n    @Override","sourceCodeStart":295,"sourceCodeEnd":331,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-core/src/main/java/org/pkl/core/stdlib/protobuf/RendererNodes.java#L295-L331","documentation":"Protobuf map keys must be directives, Long, Boolean, or String; the renderer found a map entry key of another type (e.g. a Double, IntSeq, or arbitrary object) and aborts, attaching the offending key as program value.","triggerScenarios":"Rendering a Mapping/Map to protobuf whose keys are not Long/Boolean/String — e.g. float keys, keys that are objects, or Defaultable/other Vm wrapper keys not recognized as directives.","commonSituations":"Using Pkl Mappings with non-string keys (numbers as Double from `1.0` literal, booleans via bracket syntax that resolves oddly) and rendering to protobuf; JSON-imported maps with numeric keys parsed as doubles.","solutions":["Change map keys to String (or Long/Boolean), e.g. `[\"1.0\"]` instead of `[1.0]`","Convert key values before rendering (`key.toString()` / integer literals without decimal point)","Exclude or transform non-conforming entries before protobuf rendering"],"exampleFix":"// before\nvalue = new Mapping { [1.0] = \"a\" }\n// after\nvalue = new Mapping { [\"1\"] = \"a\" }","handlingStrategy":"validation","validationCode":"function hasValidMapKeys(m) { return Object.values(m).every((entry) => typeof entry.key === 'string' || typeof entry.key === 'boolean' || Number.isInteger(entry.key)); }","typeGuard":"const isProtobufMapKey = (k) => typeof k === 'string' || typeof k === 'boolean' || Number.isInteger(k);","tryCatchPattern":"try { renderAsProtobuf(value) } catch (e) { if (e.code === 'cannotRenderProtobufProtobufKey' || e.code === 'cannotRenderProtobufMapKey') { /* coerce keys to String/Long */ } else throw e }","preventionTips":["Use String/Long/Boolean keys in Mappings rendered to protobuf","Write integer literals without a decimal point to avoid Double keys","Audit map keys of imported/converted data before protobuf rendering"],"tags":["pkl","protobuf","renderer","map-key"],"backgroundTag":"type-mismatch","analyzedSha":"f3efcbfc9b60d30053b0536d664948d7aa1b8673","analyzedAt":"2026-09-08T13:10:45.570Z","contentChangedAt":"2026-09-08T13:10:45.570Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}