{"record":{"id":"53a61d22d2a531d1","repo":"spring-projects/spring-framework","slug":"no-qualifying-bean-of-type-available-expecte-53a61d","errorCode":null,"errorMessage":"No qualifying bean of type '{}' available: expected single matching bean but found {}: {}","messagePattern":"No qualifying bean of type '(.+?)' available: expected single matching bean but found (.+?): (.+?)","errorType":"exception","errorClass":"NoUniqueBeanDefinitionException","httpStatus":null,"severity":"error","filePath":"spring-beans/src/main/java/org/springframework/beans/factory/annotation/BeanFactoryAnnotationUtils.java","lineNumber":125,"sourceCode":"\t\t\t\t\t\"BeanFactory does not implement ConfigurableListableBeanFactory.)\");\n\t\t}\n\t}\n\n\t/**\n\t * Obtain a bean of type {@code T} from the given {@code BeanFactory} declaring a qualifier\n\t * (for example, {@code <qualifier>} or {@code @Qualifier}) matching the given qualifier).\n\t * @param beanFactory the factory to get the target bean from\n\t * @param beanType the type of bean to retrieve\n\t * @param qualifier the qualifier for selecting between multiple bean matches\n\t * @return the matching bean of type {@code T} (never {@code null})\n\t */\n\tprivate static <T> T qualifiedBeanOfType(ListableBeanFactory beanFactory, Class<T> beanType, String qualifier) {\n\t\tString[] candidateBeans = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, beanType);\n\t\tString matchingBean = null;\n\t\tfor (String beanName : candidateBeans) {\n\t\t\tif (isQualifierMatch(qualifier::equals, beanName, beanFactory)) {\n\t\t\t\tif (matchingBean != null) {\n\t\t\t\t\tthrow new NoUniqueBeanDefinitionException(beanType, matchingBean, beanName);\n\t\t\t\t}\n\t\t\t\tmatchingBean = beanName;\n\t\t\t}\n\t\t}\n\t\tif (matchingBean != null) {\n\t\t\treturn beanFactory.getBean(matchingBean, beanType);\n\t\t}\n\t\telse if (beanFactory.containsBean(qualifier) && beanFactory.isTypeMatch(qualifier, beanType)) {\n\t\t\t// Fallback: target bean at least found by bean name - probably a manually registered singleton.\n\t\t\treturn beanFactory.getBean(qualifier, beanType);\n\t\t}\n\t\telse {\n\t\t\tthrow new NoSuchBeanDefinitionException(qualifier, \"No matching \" + beanType.getSimpleName() +\n\t\t\t\t\t\" bean found for qualifier '\" + qualifier + \"' - neither qualifier match nor bean name match!\");\n\t\t}\n\t}\n\n\t/**","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-beans/src/main/java/org/springframework/beans/factory/annotation/BeanFactoryAnnotationUtils.java#L107-L143","documentation":"Thrown as NoUniqueBeanDefinitionException from qualifiedBeanOfType(ListableBeanFactory, Class, String) when two or more beans of the requested type both declare the same qualifier value. The message lists the number of matches and their bean names. This means qualifier-based disambiguation failed because the qualifier was not unique among candidates.","triggerScenarios":"Two or more beans of type T are registered and both declare @Qualifier(\"sameValue\") (or an equivalent <qualifier value=\"sameValue\"/> in XML). The loop at lines 122-128 finds the first match, then encounters a second and throws.","commonSituations":"Copy-pasting @Qualifier annotations across multiple bean classes without making values unique. XML configuration where <qualifier> elements share the same value across multiple <bean> definitions. Accidentally registering the same bean under multiple names with the same qualifier.","solutions":["Make qualifier values unique across beans of the same type — each candidate should have a distinct @Qualifier value.","If both beans are genuinely needed, use @Primary on one to make it the default without qualifiers.","Consolidate duplicate bean definitions into a single bean."],"exampleFix":"// before\n@Component\n@Qualifier(\"cache\")\npublic class RedisCache implements Cache { }\n\n@Component\n@Qualifier(\"cache\")\npublic class MemcachedCache implements Cache { }\n\n// after\n@Component\n@Qualifier(\"redis\")\npublic class RedisCache implements Cache { }\n\n@Component\n@Qualifier(\"memcached\")\npublic class MemcachedCache implements Cache { }","handlingStrategy":"validation","validationCode":"// Before lookup, verify the qualifier uniquely identifies one bean\nString[] candidates = ((ListableBeanFactory) beanFactory)\n    .getBeanNamesForType(beanType);\nlong matches = Arrays.stream(candidates)\n    .filter(name -> isQualifierMatch(name, qualifier, beanFactory))\n    .count();\nif (matches > 1) {\n    throw new IllegalStateException(\"Qualifier '\" + qualifier + \"' matches \" + matches + \" beans\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    return BeanFactoryAnnotationUtils.qualifiedBeanOfType(lbf, beanType, qualifier);\n} catch (NoUniqueBeanDefinitionException ex) {\n    Collection<String> found = ex.getBeanNamesFound();\n    // disambiguate further or report the duplicate qualifier\n    throw new IllegalStateException(\"Duplicate qualifier '\" + qualifier + \"' on: \" + found, ex);\n}","preventionTips":["Ensure each @Qualifier value is unique across beans of the same type.","Use @Primary to designate a default when qualifiers are not specified.","Write a test that scans for duplicate qualifier values within the same type hierarchy."],"tags":["spring","qualifier","ambiguous-bean","di"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}