{"record":{"id":"5b35b86688994131","repo":"stanfordnlp/CoreNLP","slug":"found-a-relation-with-a-missing-slot-p","errorCode":null,"errorMessage":"Found a relation with a missing slot: ${p}","messagePattern":"Found a relation with a missing slot: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/edu/stanford/nlp/ie/KBPSemgrexExtractor.java","lineNumber":125,"sourceCode":"      if (\"O\".equals(tokens.get(i).ner())) {\n        tokens.get(i).setNER(input.objectType.name);\n      }\n    }\n\n    for (SemgrexPattern p : rulesForRel) {\n\n      SemgrexMatcher n = p.matcher(graph);\n      while (n.find()) {\n        IndexedWord entity = n.getNode(\"entity\");\n        IndexedWord slot = n.getNode(\"slot\");\n        if (entity == null) {\n          // really this is a hideous bug, right?  these rules\n          // should all have entity and slot set\n          logger.warn(\"Found a relation with a missing entity: \" + p);\n          continue;\n        }\n        if (slot == null) {\n          logger.warn(\"Found a relation with a missing slot: \" + p);\n          continue;\n        }\n        boolean hasSubject = entity.index() >= input.subjectSpan.start() + 1 && entity.index() <= input.subjectSpan.end();\n        boolean hasObject  = slot.index() >= input.objectSpan.start() + 1 && slot.index() <= input.objectSpan.end();\n        \n        if (hasSubject && hasObject) {\n          return p;\n        } \n      }\n    }\n    return null;\n  }\n\n\n  public static void main(String[] args) throws IOException {\n    RedwoodConfiguration.standard().apply();  // Disable SLF4J crap.\n    ArgumentParser.fillOptions(KBPSemgrexExtractor.class, args);\n    KBPSemgrexExtractor extractor = new KBPSemgrexExtractor(DIR);","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/ie/KBPSemgrexExtractor.java#L107-L143","documentation":"Same loop as the missing-entity case: if the 'slot' named node is not bound for a matched pattern, matches() warns with the pattern p and skips the candidate relation. The slot node is required to classify the relation by its index against the object span.","triggerScenarios":"A Semgrex KBP rule that binds 'entity' but not 'slot', or binds slot only on some branches, so certain matches reach getNode(\"slot\") returning null.","commonSituations":"Incomplete rule edits; patterns refactored where the '=slot' naming was dropped; copied patterns using different group names like '=object'.","solutions":["Name the slot node in the pattern, e.g. append '=slot' to the intended node description","Audit all KBP Semgrex patterns to ensure both '=entity' and '=slot' groups exist","If the group should be named differently, update both the pattern and this extractor code together","Test each rule against sample sentences to confirm both nodes bind"],"exampleFix":"// before\nString p = \"{word:CEO}=entity <<apposition {tag:/NN.*/}\";\n// after\nString p = \"{word:CEO}=entity <<apposition {tag:/NN.*/}=slot\";","handlingStrategy":"validation","validationCode":"if (!pattern.contains(\"=slot\")) throw new IllegalArgumentException(\"pattern missing =slot: \" + pattern);","typeGuard":null,"tryCatchPattern":"SemgrexMatcher m = p.matcher(graph);\nwhile (m.find()) {\n  IndexedWord slot = m.getNode(\"slot\");\n  if (slot == null) { log.warn(\"no slot for \" + pattern); continue; }\n  // ...\n}","preventionTips":["Pair every =entity group with an =slot group in each rule","Diff rule files after refactors to catch lost named groups","Run a smoke corpus through the extractor to surface unbound groups","Keep group naming consistent across the KBP ruleset"],"tags":["java","nlp","semgrex","rule-authoring"],"backgroundTag":"internal-invariant-violation","analyzedSha":"1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a","analyzedAt":"2026-09-10T02:24:07.274Z","contentChangedAt":"2026-09-10T02:24:07.274Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}