{"record":{"id":"b224727832820c8d","repo":"apache/beam","slug":"couldn-t-find-field-type-for-descriptor","errorCode":null,"errorMessage":"Couldn't find field type for <descriptor>","messagePattern":"Couldn't find field type for <descriptor>","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/schemas/FieldTypeDescriptors.java","lineNumber":97,"sourceCode":"\n  /** Get a {@link FieldType} from a {@link TypeDescriptor}. */\n  public static FieldType fieldTypeForJavaType(TypeDescriptor typeDescriptor) {\n    // TODO: Convert for registered logical types.\n    if (typeDescriptor.isArray()\n        || typeDescriptor.isSubtypeOf(TypeDescriptor.of(Collection.class))) {\n      return getArrayFieldType(typeDescriptor);\n    } else if (typeDescriptor.isSubtypeOf(TypeDescriptor.of(Map.class))) {\n      return getMapFieldType(typeDescriptor);\n    } else if (typeDescriptor.isSubtypeOf(TypeDescriptor.of(Iterable.class))) {\n      return getIterableFieldType(typeDescriptor);\n    } else if (typeDescriptor.isSubtypeOf(TypeDescriptor.of(Row.class))) {\n      throw new IllegalArgumentException(\n          \"Cannot automatically determine a field type from a Row class\"\n              + \" as we cannot determine the schema. You should set a field type explicitly.\");\n    } else {\n      TypeName typeName = PRIMITIVE_MAPPING.inverse().get(typeDescriptor);\n      if (typeName == null) {\n        throw new RuntimeException(\"Couldn't find field type for \" + typeDescriptor);\n      }\n      return FieldType.of(typeName);\n    }\n  }\n\n  private static FieldType getArrayFieldType(TypeDescriptor typeDescriptor) {\n    if (typeDescriptor.isArray()) {\n      if (typeDescriptor.getComponentType().getType().equals(byte.class)) {\n        return FieldType.BYTES;\n      } else {\n        return FieldType.array(fieldTypeForJavaType(typeDescriptor.getComponentType()));\n      }\n    }\n    if (typeDescriptor.isSubtypeOf(TypeDescriptor.of(Collection.class))) {\n      TypeDescriptor<Collection<?>> collection = typeDescriptor.getSupertype(Collection.class);\n      if (collection.getType() instanceof ParameterizedType) {\n        ParameterizedType ptype = (ParameterizedType) collection.getType();\n        java.lang.reflect.Type[] params = ptype.getActualTypeArguments();","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/schemas/FieldTypeDescriptors.java#L79-L115","documentation":"fieldTypeForJavaType falls back to a PRIMITIVE_MAPPING table (Java types to Beam TypeNames); if the TypeDescriptor is not in that map and is not a container, map, Row, or other handled shape, Beam cannot infer a FieldType and throws this RuntimeException. It marks an unsupported Java type in schema inference.","triggerScenarios":"Schema inference on a class whose property type is not a supported primitive or known container — e.g. java.math.BigDecimal without coder/typ registration, custom classes without schemas, org.joda.time.Instant-like types absent from the mapping.","commonSituations":"POJOs with custom value types (wrappers, third-party types); exposing library types (URI, Duration) as fields; upgrading Beam and relying on types previously mapped differently.","solutions":["Replace the unsupported property type with a supported primitive (String, Long, Double, Boolean, byte[], etc.).","Register a custom FieldType/logical type or supply the schema explicitly with FieldType.logicalType / FieldType.row.","Annotate the field with @SchemaField/ignore it if not needed, or convert it to a serializable representation in getters.","Extend FieldTypeDescriptors' mapping via a custom TypeSupplier if this type is widespread in your codebase."],"exampleFix":"// before\npublic java.net.URI getUri() { ... }\n\n// after\npublic String getUri() { return uri.toString(); } // or a logical type","handlingStrategy":"validation","validationCode":"for (Method m : pojoClass.getDeclaredMethods()) {\n  if (m.getName().startsWith(\"get\") && !SUPPORTED.contains(m.getReturnType()))\n    throw new IllegalStateException(\"unsupported field type \" + m.getReturnType());\n}","typeGuard":"static boolean isSupportedFieldType(TypeDescriptor<?> t) {\n  return t.isSubtypeOf(TypeDescriptor.of(Number.class)) || t.getType() == String.class\n      || t.getType() == Boolean.class || t.getType() == byte[].class;\n}","tryCatchPattern":"try { Schema.of(Pojo.class); }\ncatch (RuntimeException e) {\n  if (e.getMessage().startsWith(\"Couldn't find field type for\")) {\n    throw new IllegalStateException(\"Replace or register the unsupported property type\", e);\n  } throw e;\n}","preventionTips":["Restrict POJO fields to Beam-supported primitives and containers","Model custom value types as logical types or convert in accessors","Add a schema-inference smoke test for domain POJOs"],"tags":["beam-schemas","type-inference","unsupported-type"],"backgroundTag":"unsupported-dtype","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}