{"record":{"id":"0f7d24a6a2767e61","repo":"apache/flink","slug":"unable-to-extract-key-from-expression-keyexpr","errorCode":null,"errorMessage":"Unable to extract key from expression '{keyExpr}' on key {cType}","messagePattern":"Unable to extract key from expression '(.+?)' on key (.+?)","errorType":"exception","errorClass":"InvalidProgramException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/api/common/operators/Keys.java","lineNumber":318,"sourceCode":"\n            if (type instanceof CompositeType) {\n                CompositeType<T> cType = (CompositeType<T>) type;\n                this.originalKeyTypes = new TypeInformation<?>[keyExpressions.length];\n\n                // extract the keys on their flat position\n                for (int i = 0; i < keyExpressions.length; i++) {\n                    String keyExpr = keyExpressions[i];\n\n                    if (keyExpr == null) {\n                        throw new InvalidProgramException(\"Expression key may not be null.\");\n                    }\n                    // strip off whitespace\n                    keyExpr = keyExpr.trim();\n\n                    List<FlatFieldDescriptor> flatFields = cType.getFlatFields(keyExpr);\n\n                    if (flatFields.size() == 0) {\n                        throw new InvalidProgramException(\n                                \"Unable to extract key from expression '\"\n                                        + keyExpr\n                                        + \"' on key \"\n                                        + cType);\n                    }\n                    // check if all nested fields can be used as keys\n                    for (FlatFieldDescriptor field : flatFields) {\n                        if (!field.getType().isKeyType()) {\n                            throw new InvalidProgramException(\n                                    \"This type (\" + field.getType() + \") cannot be used as key.\");\n                        }\n                    }\n                    // add flat fields to key fields\n                    keyFields.addAll(flatFields);\n\n                    String strippedKeyExpr = WILD_CARD_REGEX.matcher(keyExpr).replaceAll(\"\");\n                    if (strippedKeyExpr.isEmpty()) {\n                        this.originalKeyTypes[i] = type;","sourceCodeStart":300,"sourceCodeEnd":336,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/api/common/operators/Keys.java#L300-L336","documentation":"Thrown by ExpressionKeys(String[], TypeInformation) when cType.getFlatFields(keyExpr) returns an empty list, i.e. the expression does not match any field on the composite type. The expression may be misspelled, reference a non-existent nested path, or target a field not present in the POJO/Tuple schema.","triggerScenarios":"Calling groupBy(\"usrId\") instead of groupBy(\"userId\"); referencing a nested path like \"address.zip\" on a POJO whose address field has no zip; using a field name valid on one schema but not the runtime type.","commonSituations":"Typos in field-expression keys; schema drift where a field was renamed or removed; copy-pasting a key from a different dataset's schema; case-sensitivity mismatches on POJO field names.","solutions":["Verify the field name exactly matches the POJO/Tuple field (case-sensitive for POJOs).","For nested fields, confirm each path segment exists and is correctly named.","Print the type's field names (cType.getFieldNames()) to compare against your expression."],"exampleFix":"// before (POJO field is 'userId')\nds.groupBy(\"usrId\");\n// after\nds.groupBy(\"userId\");","handlingStrategy":"validation","validationCode":"List<FlatFieldDescriptor> resolved = cType.getFlatFields(keyExpr);\nif (resolved.isEmpty()) {\n    throw new IllegalArgumentException(\n        \"No field matches expression '\" + keyExpr + \"' on \" + cType + \". Known fields: \"\n            + Arrays.toString(cType.getFieldNames()));\n}","typeGuard":"static boolean fieldExists(CompositeType<?> t, String expr) {\n    try { return !t.getFlatFields(expr).isEmpty(); }\n    catch (Throwable x) { return false; }\n}","tryCatchPattern":null,"preventionTips":["Match the exact field name (case-sensitive for POJOs).","Print cType.getFieldNames() to compare against your expression when unsure.","For nested paths, confirm each segment exists before composing the expression."],"tags":["flink-core","keys","expression-keys","field-resolution","validation"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}