{"record":{"id":"30fdaa3f575b1577","repo":"alibaba/spring-ai-alibaba","slug":"strategy-type-cannot-be-null-or-empty","errorCode":null,"errorMessage":"Strategy type cannot be null or empty","messagePattern":"Strategy type cannot be null or empty","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/flow/strategy/FlowGraphBuildingStrategyRegistry.java","lineNumber":65,"sourceCode":"\t * @return the registry instance\n\t */\n\tpublic static FlowGraphBuildingStrategyRegistry getInstance() {\n\t\treturn INSTANCE;\n\t}\n\n\t/**\n\t * Registers a new graph building strategy (same instance returned each time).\n\t * @param strategy the strategy to register\n\t * @throws IllegalArgumentException if strategy is null or type is already registered\n\t */\n\tpublic void registerStrategy(FlowGraphBuildingStrategy strategy) {\n\t\tif (strategy == null) {\n\t\t\tthrow new IllegalArgumentException(\"Strategy cannot be null\");\n\t\t}\n\n\t\tString type = strategy.getStrategyType();\n\t\tif (type == null || type.trim().isEmpty()) {\n\t\t\tthrow new IllegalArgumentException(\"Strategy type cannot be null or empty\");\n\t\t}\n\n\t\tif (strategyFactories.containsKey(type)) {\n\t\t\tthrow new IllegalArgumentException(\"Strategy type '\" + type + \"' is already registered\");\n\t\t}\n\n\t\tstrategyFactories.put(type, () -> strategy);\n\t}\n\n\t/**\n\t * Registers a strategy factory. Each call to {@link #createStrategy(String)} or\n\t * {@link #getStrategy(String)} will use the factory to obtain a strategy instance.\n\t * @param type the strategy type\n\t * @param factory the factory that creates strategy instances\n\t * @throws IllegalArgumentException if type or factory is null, or type is already registered\n\t */\n\tpublic void registerStrategy(String type, Supplier<FlowGraphBuildingStrategy> factory) {\n\t\tif (type == null || type.trim().isEmpty()) {","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/flow/strategy/FlowGraphBuildingStrategyRegistry.java#L47-L83","documentation":"registerStrategy derives the registry key from strategy.getStrategyType(); a null or blank type cannot serve as a lookup key, so IllegalArgumentException is thrown. The registry also rejects duplicate types with a separate error ('Strategy type ... is already registered').","triggerScenarios":"Registering a custom FlowGraphBuildingStrategy whose getStrategyType() returns null, \"\", or whitespace (e.g. a constant not initialized or a typo returning an empty string).","commonSituations":"Custom strategy class with getStrategyType() wired to an unset config property; copy-pasted strategy with forgotten type override; internationalization accidentally blanking the constant.","solutions":["Implement getStrategyType() to return a fixed non-blank constant (e.g. return \"custom-conditional\";)","If the type is configurable, validate/trim it in the strategy constructor and fall back to a default","Add a constructor assertion: Objects.requireNonNull(type); if (type.isBlank()) throw ..."],"exampleFix":"// before\n@Override public String getStrategyType() { return configuredType; }\n// after\n@Override public String getStrategyType() {\n    return (configuredType == null || configuredType.isBlank())\n        ? \"custom\" : configuredType.trim();\n}","handlingStrategy":"validation","validationCode":"String t = strategy.getStrategyType(); if (t == null || t.trim().isEmpty()) throw new IllegalArgumentException(strategy.getClass().getName() + \" returned blank strategy type\");","typeGuard":"static boolean hasValidType(FlowGraphBuildingStrategy s) { String t = s.getStrategyType(); return t != null && !t.trim().isEmpty(); }","tryCatchPattern":"try { registry.registerStrategy(strategy); } catch (IllegalArgumentException e) { throw new StrategyRegistrationException(e.getMessage(), e); }","preventionTips":["Return fixed constants from getStrategyType(), never config-derived values without defaults","Assert the type in the strategy constructor","Check for duplicate registrations too ('already registered' is a sibling error)"],"tags":["configuration","registry","validation"],"backgroundTag":"empty-required-field","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}