{"record":{"id":"d9e4bffd14996ff7","repo":"chinabugotech/hutool","slug":"attribute-cannot-mirror-for-because","errorCode":null,"errorMessage":"attribute [{}] cannot mirror for [{}], because [{}] already mirrored for [{}] and  [{}] already mirrored for [{}]","messagePattern":"attribute \\[(.+?)\\] cannot mirror for \\[(.+?)\\], because \\[(.+?)\\] already mirrored for \\[(.+?)\\] and  \\[(.+?)\\] already mirrored for \\[(.+?)\\]","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hutool-core/src/main/java/cn/hutool/core/annotation/MirrorLinkAnnotationPostProcessor.java","lineNumber":111,"sourceCode":"\t\t}\n\t\t// 镜像字段已经跟其他字段形成镜像\n\t\telse if (!originalAttributeMirrored && mirrorAttributeMirrored) {\n\t\t\terrorMsg = CharSequenceUtil.format(\n\t\t\t\t\"attribute [{}] cannot mirror for [{}], because it's already mirrored for [{}]\",\n\t\t\t\tmirror.getAttribute(), original.getAttribute(), ((MirroredAnnotationAttribute)mirror).getLinked()\n\t\t\t);\n\t\t}\n\t\t// 两者都形成了镜像，但是都未指向对方，理论上不会存在该情况\n\t\telse {\n\t\t\terrorMsg = CharSequenceUtil.format(\n\t\t\t\t\"attribute [{}] cannot mirror for [{}], because [{}] already mirrored for [{}] and  [{}] already mirrored for [{}]\",\n\t\t\t\tmirror.getAttribute(), original.getAttribute(),\n\t\t\t\tmirror.getAttribute(), ((MirroredAnnotationAttribute)mirror).getLinked(),\n\t\t\t\toriginal.getAttribute(), ((MirroredAnnotationAttribute)original).getLinked()\n\t\t\t);\n\t\t}\n\n\t\tthrow new IllegalArgumentException(errorMsg);\n\t}\n\n\t/**\n\t * 基本校验\n\t */\n\tprivate void checkMirrorRelation(Link annotation, AnnotationAttribute original, AnnotationAttribute mirror) {\n\t\t// 镜像属性必须存在\n\t\tcheckLinkedAttributeNotNull(original, mirror, annotation);\n\t\t// 镜像属性返回值必须一致\n\t\tcheckAttributeType(original, mirror);\n\t\t// 镜像属性上必须存在对应的注解\n\t\tfinal Link mirrorAttributeAnnotation = getLinkAnnotation(mirror, RelationType.MIRROR_FOR);\n\t\tAssert.isTrue(\n\t\t\tObjectUtil.isNotNull(mirrorAttributeAnnotation) && RelationType.MIRROR_FOR.equals(mirrorAttributeAnnotation.type()),\n\t\t\t\"mirror attribute [{}] of original attribute [{}] must marked by @Link, and also @LinkType.type() must is [{}]\",\n\t\t\tmirror.getAttribute(), original.getAttribute(), RelationType.MIRROR_FOR\n\t\t);\n\t\tcheckLinkedSelf(original, mirror);","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/chinabugotech/hutool/blob/8870454b2a0c29cc6ffd31dcf5667c8ceb2fc442/hutool-core/src/main/java/cn/hutool/core/annotation/MirrorLinkAnnotationPostProcessor.java#L93-L129","documentation":"The other branch of the same check: both mirrored attributes already point at different targets, so neither can additionally mirror the other. The processor treats this as an unrecoverable inconsistent state and throws IllegalArgumentException with both link targets enumerated. The comment notes this case is theoretically unreachable but is guarded defensively.","triggerScenarios":"An annotation-processing or synthesis bug where both A and B have already been wrapped as MirroredAnnotationAttribute linked to third parties; can appear when multiple AnnotationPostProcessors run and one has already rewired links before MirrorLinkAnnotationPostProcessor validates.","commonSituations":"Custom AnnotationPostProcessor registered ahead of MirrorLinkAnnotationPostProcessor that mutates link relationships; duplicate mirror declarations across a meta-annotation chain.","solutions":["Audit custom AnnotationPostProcessor implementations for link mutation; register them after the mirror processor.","Eliminate duplicate/overlapping @Link MIRROR_FOR declarations across the annotation hierarchy.","Simplify the annotation composition to a single explicit mirror pair and rebuild."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { synth.setAttribute(n, v); } catch (UnsupportedOperationException e) { if (e.getMessage().contains(\"proxied\")) { /* mutate underlying */ } else throw e; }","preventionTips":["Register custom AnnotationPostProcessors after MirrorLinkAnnotationPostProcessor.","Keep annotation hierarchies free of duplicate MIRROR_FOR links."],"tags":["annotation","mirror","link","reflection"],"backgroundTag":null,"analyzedSha":"8870454b2a0c29cc6ffd31dcf5667c8ceb2fc442","analyzedAt":"2026-08-14T04:01:12.892Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}