{"record":{"id":"5bde5c90c572b374","repo":"apache/pulsar","slug":"external-schema-cannot-be-used-with-other-pulsar-s","errorCode":null,"errorMessage":"External schema cannot be used with other Pulsar struct schema types,keySchemaType: ${keySchemaType}, valueSchemaType: ${valueSchemaType}","messagePattern":"External schema cannot be used with other Pulsar struct schema types,keySchemaType: (.+?), valueSchemaType: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-client/src/main/java/org/apache/pulsar/client/impl/schema/KeyValueSchemaImpl.java","lineNumber":121,"sourceCode":"        this(keySchema, valueSchema, KeyValueEncodingType.INLINE);\n    }\n\n    private KeyValueSchemaImpl(Schema<K> keySchema,\n                               Schema<V> valueSchema,\n                               KeyValueEncodingType keyValueEncodingType) {\n        SchemaType keySchemaType = null;\n        if (keySchema != null && keySchema.getSchemaInfo() != null) {\n            keySchemaType = keySchema.getSchemaInfo().getType();\n        }\n        SchemaType valueSchemaType = null;\n        if (valueSchema != null && valueSchema.getSchemaInfo() != null) {\n            valueSchemaType = valueSchema.getSchemaInfo().getType();\n        }\n        if ((SchemaType.EXTERNAL.equals(keySchemaType)\n                && valueSchemaType != null && SchemaType.isStructType(valueSchemaType))\n                || (SchemaType.EXTERNAL.equals(valueSchemaType)\n                && keySchemaType != null && SchemaType.isStructType(keySchemaType))) {\n            throw new IllegalArgumentException(\"External schema cannot be used with other Pulsar struct schema types,\"\n                    + \"keySchemaType: \" + keySchemaType + \", valueSchemaType: \" + valueSchemaType);\n        }\n\n        this.keySchema = keySchema;\n        this.valueSchema = valueSchema;\n        this.keyValueEncodingType = keyValueEncodingType;\n        this.schemaInfoProvider = new SchemaInfoProvider() {\n            @Override\n            public CompletableFuture<SchemaInfo> getSchemaByVersion(byte[] schemaVersion) {\n                return CompletableFuture.completedFuture(schemaInfo);\n            }\n\n            @Override\n            public CompletableFuture<SchemaInfo> getLatestSchema() {\n                return CompletableFuture.completedFuture(schemaInfo);\n            }\n\n            @Override","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client/src/main/java/org/apache/pulsar/client/impl/schema/KeyValueSchemaImpl.java#L103-L139","documentation":"KeyValueSchemaImpl's constructor validates the combination of key and value schema types. An EXTERNAL schema (schema fetched from an external registry with unknown Pulsar type) may not be paired with a Pulsar struct type (AVRO/JSON/PROTO) on the other side, because the decoding semantics are incompatible; it throws IllegalArgumentException.","triggerScenarios":"Constructing Schema.KeyValue(keySchema, valueSchema, encodingType) where one side's SchemaInfo.getType() is EXTERNAL and the other side is a struct type (AVRO/JSON/Protobuf).","commonSituations":"Mixing an auto-discovered/registry-backed schema with a locally defined POJO schema in a KeyValue; programmatic schema composition where one side's type defaults to EXTERNAL.","solutions":["Use struct schemas for both key and value (e.g. Schema.AVRO(K.class) and Schema.AVRO(V.class))","Or use EXTERNAL consistently for both sides if schemas come from an external registry","Inspect getSchemaInfo().getType() of both schemas before composing the KeyValue and pick compatible types"],"exampleFix":"// before\nSchema<KeyValue<MyKey,MyVal>> s = Schema.KeyValue(Schema.EXTERNAL(SomeSchemaInfo.class), Schema.AVRO(MyVal.class), KeyValueEncodingType.INLINE);\n// after\nSchema<KeyValue<MyKey,MyVal>> s = Schema.KeyValue(Schema.AVRO(MyKey.class), Schema.AVRO(MyVal.class), KeyValueEncodingType.INLINE);","handlingStrategy":"validation","validationCode":"SchemaType kt = keySchema.getSchemaInfo().getType(); SchemaType vt = valueSchema.getSchemaInfo().getType();\nboolean bad = (kt == SchemaType.EXTERNAL && SchemaType.isStructType(vt)) || (vt == SchemaType.EXTERNAL && SchemaType.isStructType(kt));\nif (bad) throw new IllegalArgumentException(\"EXTERNAL schema cannot be paired with struct schema: \" + kt + \"/\" + vt);","typeGuard":"boolean compatibleKvPair(Schema<?> k, Schema<?> v) { SchemaType kt = k.getSchemaInfo().getType(); SchemaType vt = v.getSchemaInfo().getType(); return (kt == SchemaType.EXTERNAL) == (vt == SchemaType.EXTERNAL) || (!SchemaType.isStructType(kt) && !SchemaType.isStructType(vt)); }","tryCatchPattern":"try { Schema<KeyValue<K,V>> s = Schema.KeyValue(k, v, enc); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"External schema cannot be used\")) { /* rebuild with matching types */ } else throw e; }","preventionTips":["Log both schema types before composing KeyValue schemas","Keep EXTERNAL only for registry-driven both-sides usage","Prefer explicit AVRO/JSON schemas on both sides"],"tags":["schema","keyvalue","external-schema"],"backgroundTag":"incompatible-keyvalue-schema-types","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}