{"record":{"id":"57a5c22346363090","repo":"google/guava","slug":"annotation-explicitly-or-implicitly-requires-one-o","errorCode":null,"errorMessage":"Annotation explicitly or implicitly requires one or more features to be both present and absent.","messagePattern":"Annotation explicitly or implicitly requires one or more features to be both present and absent\\.","errorType":"exception","errorClass":"ConflictingRequirementsException","httpStatus":null,"severity":"error","filePath":"android/guava-testlib/src/com/google/common/collect/testing/features/FeatureUtil.java","lineNumber":195,"sourceCode":"   * @param testerAnnotation a tester annotation\n   * @return the requirements specified by the annotation\n   * @throws ConflictingRequirementsException if the requirements are mutually inconsistent.\n   */\n  private static TesterRequirements buildTesterRequirements(Annotation testerAnnotation)\n      throws ConflictingRequirementsException {\n    Class<? extends Annotation> annotationClass = testerAnnotation.annotationType();\n    Feature<?>[] presentFeatures;\n    Feature<?>[] absentFeatures;\n    try {\n      presentFeatures = (Feature<?>[]) annotationClass.getMethod(\"value\").invoke(testerAnnotation);\n      absentFeatures = (Feature<?>[]) annotationClass.getMethod(\"absent\").invoke(testerAnnotation);\n    } catch (Exception e) {\n      throw new IllegalArgumentException(\"Error extracting features from tester annotation.\", e);\n    }\n    Set<Feature<?>> allPresentFeatures = addImpliedFeatures(copyToSet(presentFeatures));\n    Set<Feature<?>> allAbsentFeatures = copyToSet(absentFeatures);\n    if (!disjoint(allPresentFeatures, allAbsentFeatures)) {\n      throw new ConflictingRequirementsException(\n          \"Annotation explicitly or \"\n              + \"implicitly requires one or more features to be both present \"\n              + \"and absent.\",\n          intersection(allPresentFeatures, allAbsentFeatures),\n          testerAnnotation);\n    }\n    return new TesterRequirements(allPresentFeatures, allAbsentFeatures);\n  }\n\n  /**\n   * Construct the set of requirements specified by annotations directly on a tester class or\n   * method.\n   *\n   * @param classOrMethod a tester class or a test method thereof\n   * @return all the constraints implicitly or explicitly required by annotations on the class or\n   *     method.\n   * @throws ConflictingRequirementsException if the requirements are mutually inconsistent.\n   */","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/google/guava/blob/94f39958baf7ad51ddf9c70e406ed6b188194daa/android/guava-testlib/src/com/google/common/collect/testing/features/FeatureUtil.java#L177-L213","documentation":"Thrown as ConflictingRequirementsException when a single tester annotation requires a feature to be both present (via value()) and absent (via absent()), after implied-feature expansion. The library treats presence and absence of the same feature as an unsatisfiable constraint, so the test cannot be meaningfully run.","triggerScenarios":"A @Feature.Require that lists a feature in value() and the same (or an implying/implied) feature in absent(); or a feature whose implied set overlaps the absent set after addImpliedFeatures runs.","commonSituations":"Copy-pasting an annotation and editing only one side; listing a compound feature (e.g. GENERAL_PURPOSE) in value while listing an implied sub-feature in absent; feature-enum changes that add new implications across versions.","solutions":["Inspect the exception's getConflicts() set to see exactly which features are present and absent simultaneously.","Remove the feature from either value() or absent() so the two sets are disjoint after implied-feature expansion.","If the conflict comes from implied features, replace the compound feature with the specific sub-features you actually want."],"exampleFix":"// before\n@MapFeature.Require(value = {SUPPORTS_PUT}, absent = {SUPPORTS_PUT})\npublic void testPut() { ... }\n\n// after\n@MapFeature.Require(SUPPORTS_PUT)\npublic void testPut() { ... }","handlingStrategy":"validation","validationCode":"// Before declaring a tester annotation, check value/absent disjointness after implication.\nSet<Feature<?>> present = addImpliedFeatures(copyToSet(req.value()));\nSet<Feature<?>> absent = copyToSet(req.absent());\nif (!Collections.disjoint(present, absent))\n  throw new IllegalArgumentException(\"annotation present/absent overlap: \" + Sets.intersection(present, absent));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never list the same feature in both value() and absent().","Remember compound features imply their members; avoid combining a compound in value with a member in absent."],"tags":["guava-testlib","annotations","features","conflicting-requirements"],"backgroundTag":null,"analyzedSha":"94f39958baf7ad51ddf9c70e406ed6b188194daa","analyzedAt":"2026-08-13T22:50:30.265Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}