{"record":{"id":"696ed03ea0b7c08f","repo":"elastic/elasticsearch","slug":"s-module-does-not-declare-uses-s","errorCode":null,"errorMessage":"%s: module does not declare uses %s","messagePattern":"(.+?): module does not declare uses (.+?)","errorType":"exception","errorClass":"ServiceConfigurationError","httpStatus":null,"severity":"error","filePath":"libs/core/src/main/java/org/elasticsearch/core/internal/provider/ProviderLocator.java","lineNumber":55,"sourceCode":" */\npublic final class ProviderLocator<T> implements Supplier<T> {\n\n    private final String providerName;\n    private final Class<T> providerType;\n    private final String providerModuleName;\n\n    private final ClassLoader parentLoader;\n\n    private final Set<String> missingModules;\n\n    // whether to load the provider implementation as a module or not\n    private final boolean loadAsProviderModule;\n\n    /** Checks that the module of the given type declares that it uses said type. */\n    static <P> Class<P> checkUses(Class<P> providerType) {\n        Module caller = providerType.getModule();\n        if (caller.isNamed() && caller.getDescriptor().uses().stream().anyMatch(providerType.getName()::equals) == false) {\n            throw new ServiceConfigurationError(String.format(Locale.ROOT, \"%s: module does not declare uses %s\", caller, providerType));\n        }\n        return providerType;\n    }\n\n    public ProviderLocator(String providerName, Class<T> providerType, String providerModuleName, Set<String> missingModules) {\n        this(\n            providerName,\n            checkUses(providerType),\n            ProviderLocator.class.getClassLoader(),\n            providerModuleName,\n            missingModules,\n            ProviderLocator.class.getModule().isNamed()\n        );\n    }\n\n    // package-private for testing\n    ProviderLocator(\n        String providerName,","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/core/src/main/java/org/elasticsearch/core/internal/provider/ProviderLocator.java#L37-L73","documentation":"Thrown as a ServiceConfigurationError by ProviderLocator.checkUses when the module owning the provider type is a named module but its descriptor does not declare a `uses` directive for that provider type. Java's ServiceLoader contract requires a module to declare `uses <service>` before it can load providers for that service; ProviderLocator enforces this eagerly at construction so the failure surfaces at the locator call site rather than later during loading.","triggerScenarios":"Constructing a `new ProviderLocator(name, ProviderType.class, moduleName, missingModules)` from within a named module whose module-info does not contain `uses <fully.qualified.ProviderType>`. The check at line 54 fires when the module's uses() set lacks the provider type's name.","commonSituations":"Adding a ServiceLoader-based provider lookup to a module but forgetting to add the `uses` directive in module-info.java. Refactoring the provider type to a new package without updating module-info. Splitting a module and dropping the uses directive. Running code that previously worked on the classpath (unnamed module — check is skipped) once the module system is engaged.","solutions":["Add `uses <fully.qualified.ProviderType>;` to the module-info.java of the module that constructs the ProviderLocator.","Confirm the fully-qualified name in `uses` exactly matches the Class passed to ProviderLocator (including package).","If the call site moved to a different module, add the uses directive to that module instead.","Rebuild and re-run — module-info changes take effect at compile/load time."],"exampleFix":"// before — module-info.java\nmodule my.mod {\n    requires elasticsearch.core;\n}\n\n// after\nmodule my.mod {\n    requires elasticsearch.core;\n    uses org.elasticsearch.xcontent.XContentProvider;\n}","handlingStrategy":"validation","validationCode":"// Verify a module declares `uses` for a service type before constructing ProviderLocator\nboolean declaresUses(Class<?> service) {\n    Module m = service.getModule();\n    return !m.isNamed() || m.getDescriptor().uses().contains(service.getName());\n}","typeGuard":"static boolean moduleDeclaresUses(Class<?> service) {\n    Module m = service.getModule();\n    return m.isNamed() && m.getDescriptor().uses().contains(service.getName());\n}","tryCatchPattern":"try {\n    return new ProviderLocator<>(name, type, moduleName, missingModules).get();\n} catch (ServiceConfigurationError e) {\n    if (e.getMessage().contains(\"does not declare uses\")) {\n        // fix module-info.java of the calling module to add `uses <type>;` then rebuild\n        throw new RuntimeException(\"module-info missing 'uses \" + type.getName() + \"'\", e);\n    }\n    throw e;\n}","preventionTips":["Add `uses <service>;` to module-info.java of any module that calls ProviderLocator/ServiceLoader.load.","When refactoring a service type to a new package, update the uses directive in lockstep.","Remember: the unnamed module (classpath) skips this check — engage JPMS early in tests.","Treat ServiceConfigurationError as fatal at startup, not retried."],"tags":["modules","jpms","service-loader","provider","elasticsearch-core","configuration"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T11:17:21.771Z"}