{"record":{"id":"80bdc7eebf231126","repo":"stanfordnlp/CoreNLP","slug":"cannot-process-a-single-key-value-from-annotation","errorCode":null,"errorMessage":"Cannot process a single key/value from annotation  as it is not a Map","messagePattern":"Cannot process a single key/value from annotation  as it is not a Map","errorType":"validation","errorClass":"SemgrexParseException","httpStatus":null,"severity":"error","filePath":"src/edu/stanford/nlp/semgraph/semgrex/NodePattern.java","lineNumber":107,"sourceCode":"      }\n\n      if (negated) {\n        descString += (key + \"!:\" + value);\n      } else {\n        descString += (key + ':' + value);\n      }\n    }\n\n    for (Quadruple<String, String, String, Boolean> entry : attrs.contains()) {\n      String annotation = entry.first();\n      String key = entry.second();\n      String value = entry.third();\n      boolean negated = entry.fourth();\n\n      Class<?> clazz = AnnotationLookup.getValueType(AnnotationLookup.toCoreKey(annotation));\n      boolean isMap = clazz != null && Map.class.isAssignableFrom(clazz);\n      if (!isMap) {\n        throw new SemgrexParseException(\"Cannot process a single key/value from annotation \" + annotation + \" as it is not a Map\"); \n      }\n\n      final Attribute attr;\n      if (key.equals(\"__\")) {\n        regexPartialAttributes.add(new RegexPartialAttribute(annotation, \"/.*/\", value, negated));\n      } else if (key.matches(\"/.*/\")) {\n        regexPartialAttributes.add(new RegexPartialAttribute(annotation, key, value, negated));\n      } else {\n        // Add the attributes for this key\n        if (value.equals(\"__\")) {\n          attr = new Attribute(key, true, true, negated);\n        } else if (value.matches(\"/.*/\")) {\n          attr = buildRegexAttribute(key, value, negated);\n        } else { // raw description\n          attr = new Attribute(key, value, value, negated);\n        }\n        partialAttributes.add(new Pair<>(annotation, attr));\n      }","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/semgraph/semgrex/NodePattern.java#L89-L125","documentation":"When converting node attributes to a Pattern, a single key/value pair can only be extracted from annotations whose value type is a Map (e.g. CoreDataMap-like annotations). If AnnotationLookup reports the annotation's type is not a Map, NodePattern throws SemgrexParseException because key/value matching inside that annotation is meaningless.","triggerScenarios":"Using map-style key/value matching syntax (e.g. 'key=value' inside an annotation such as 'Biennium...') against a CoreAnnotation whose getValueType is not a Map subtype (clazz==null or not Map.assignable).","commonSituations":"Applying map-subattribute semgrex syntax to scalar annotations like Text, Lemma, or POS; typos in the annotation key so AnnotationLookup.toCoreKey resolves to a non-Map annotation or null.","solutions":["Use a Map-valued annotation (e.g. one whose values are Maps of attributes) for key/value matching","Match the scalar annotation directly (e.g. /regex/ on the annotation) instead of key=value inside it","Fix the annotation key spelling so it resolves to the intended Map-valued CoreAnnotation"],"exampleFix":"// before\n[{word/foo=bar}] // word is not a Map annotation\n// after\n[{ner/TAG=PERSON}] // use a Map-valued annotation for key=value","handlingStrategy":"validation","validationCode":"Class<?> clazz = AnnotationLookup.getValueType(AnnotationLookup.toCoreKey(annotation)); if (clazz == null || !Map.class.isAssignableFrom(clazz)) throw new IllegalArgumentException(annotation + \" is not a Map annotation\");","typeGuard":"boolean isMapAnnotation(String ann) { Class<?> c = AnnotationLookup.getValueType(AnnotationLookup.toCoreKey(ann)); return c != null && Map.class.isAssignableFrom(c); }","tryCatchPattern":"try { buildNodePattern(entries); } catch (SemgrexParseException e) { log.error(e.getMessage()); }","preventionTips":["Only use key=value sub-matching on Map-valued annotations","Resolve annotation keys via AnnotationLookup before parsing","Test patterns against a sample CoreMap before production use"],"tags":["java","semgrex","type-mismatch","annotations"],"backgroundTag":"type-mismatch","analyzedSha":"1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a","analyzedAt":"2026-09-10T02:24:07.274Z","contentChangedAt":"2026-09-10T02:24:07.274Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}