{"record":{"id":"f3af517a2db3a648","repo":"permissions-dispatcher/PermissionsDispatcher","slug":"value-is-duplicated-in-e-simplestring-an","errorCode":null,"errorMessage":"$value is duplicated in '${e.simpleString()}()' annotated with '@${annotation.simpleName}'","messagePattern":"\\$value is duplicated in '(.+?)\\(\\)' annotated with '@(.+?)'","errorType":"validation","errorClass":"DuplicatedValueException","httpStatus":null,"severity":"error","filePath":"processor/src/main/kotlin/permissions/dispatcher/processor/util/Validators.kt","lineNumber":41,"sourceCode":"    val type = element.asType()\n    try {\n        return units.first { type.isSubtypeOf(it.getTargetType()) }\n    } catch (ex: NoSuchElementException) {\n        throw WrongClassException(type)\n    }\n}\n\n/**\n * Checks the elements in the provided list annotated with an annotation against duplicate values.\n * <p>\n * Raises an exception if any annotation value is found multiple times.\n */\nfun <A : Annotation> checkDuplicatedValue(items: List<ExecutableElement>, annotationClass: Class<A>) {\n    val allItems: HashSet<List<String>> = hashSetOf()\n    items.forEach {\n        val permissionValue = it.getAnnotation(annotationClass).permissionValue().sorted()\n        if (allItems.contains(permissionValue)) {\n            throw DuplicatedValueException(permissionValue, it, annotationClass)\n        } else {\n            allItems.add(permissionValue)\n        }\n    }\n}\n\n/**\n * Checks the elements in the provided list for elements.\n * <p>\n * Raises an exception if it doesn't contain any elements.\n */\nfun <A : Annotation> checkNotEmpty(items: List<ExecutableElement>, rpe: RuntimePermissionsElement, annotationClass: Class<A>) {\n    if (items.isEmpty()) {\n        throw NoAnnotatedMethodsException(rpe, annotationClass)\n    }\n}\n\n/**","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/permissions-dispatcher/PermissionsDispatcher/blob/74b532bf1fe430fb12ad8414b80399f2d7cfc954/processor/src/main/kotlin/permissions/dispatcher/processor/util/Validators.kt#L23-L59","documentation":"Thrown by checkDuplicatedValue in Validators.kt:41. When multiple methods in one annotated class request the exact same permission set via @NeedsPermission (or @OnPermissionDenied etc.), the processor detects the duplicate sorted permissionValue list and throws DuplicatedValueException. Each permission combination must map to a single method so generated dispatch code stays unambiguous.","triggerScenarios":"Two methods in the same @RuntimePermissions class are annotated with identical permission arrays, e.g. two methods both @NeedsPermission(Manifest.permission.CAMERA), or same set in different order (order-insensitive because values are sorted before comparison).","commonSituations":"Copy-pasting an annotated method and forgetting to change its permissions; two overloads annotated with the same permissions; merging branches that each added a method for the same permission.","solutions":["Remove or rename the duplicated annotation so only one method requests that exact permission set.","Differentiate the methods by giving them distinct permission lists.","Merge the duplicated methods into a single method called from both call sites."],"exampleFix":"// before\n@NeedsPermission(Manifest.permission.CAMERA)\nfun showCamera() { }\n@NeedsPermission(Manifest.permission.CAMERA)\nfun openCamera() { }\n\n// after\n@NeedsPermission(Manifest.permission.CAMERA)\nfun showCamera() { } // single method; call showCamera() from both places","handlingStrategy":"validation","validationCode":"val perms = mapOf(\n  \"showCamera\" to listOf(CAMERA),\n  \"openGallery\" to listOf(READ_MEDIA_IMAGES)\n)\nrequire(perms.values.toSet().size == perms.size) { \"duplicate permission sets\" }","typeGuard":null,"tryCatchPattern":"try {\n    buildProject()\n} catch (e: CompilationError) {\n    logger.error(\"Duplicate @NeedsPermission values: give each method a unique permission set\", e)\n}","preventionTips":["One method per unique permission combination.","Name methods after the permission set they request.","Review diff when copy-pasting annotated methods."],"tags":["kotlin","annotation-processor","duplicate"],"backgroundTag":"conflicting-config-options","analyzedSha":"74b532bf1fe430fb12ad8414b80399f2d7cfc954","analyzedAt":"2026-09-08T21:44:58.380Z","contentChangedAt":"2026-09-08T21:44:58.380Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}