{"record":{"id":"49ccb9dc84927150","repo":"gradle/gradle","slug":"can-not-inject-repositoryresourceaccessor-since-re","errorCode":null,"errorMessage":"Can not inject RepositoryResourceAccessor since repository has no URL.","messagePattern":"Can not inject RepositoryResourceAccessor since repository has no URL\\.","errorType":"exception","errorClass":"ServiceLookupException","httpStatus":null,"severity":"error","filePath":"platforms/software/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/AbstractArtifactRepository.java","lineNumber":217,"sourceCode":"\n    private static class RepositoryRuleServiceLookup implements ServiceLookup {\n\n        private final ObjectFactory objectFactory;\n        private final @Nullable RepositoryResourceAccessor repositoryResourceAccessor;\n\n        public RepositoryRuleServiceLookup(\n            ObjectFactory objectFactory,\n            @Nullable RepositoryResourceAccessor repositoryResourceAccessor\n        ) {\n            this.objectFactory = objectFactory;\n            this.repositoryResourceAccessor = repositoryResourceAccessor;\n        }\n\n        @Override\n        public @Nullable Object find(Type serviceType) throws ServiceLookupException {\n            if (serviceType == RepositoryResourceAccessor.class) {\n                if (repositoryResourceAccessor == null) {\n                    throw new ServiceLookupException(\"Can not inject RepositoryResourceAccessor since repository has no URL.\");\n                } else {\n                    return repositoryResourceAccessor;\n                }\n            } else if (serviceType == ObjectFactory.class) {\n                return objectFactory;\n            }\n\n            return null;\n        }\n\n        @Override\n        public Object get(Type serviceType) throws UnknownServiceException, ServiceLookupException {\n            Object service = find(serviceType);\n            if (service != null) {\n                return service;\n            }\n            throw new UnknownServiceException(serviceType, \"Service of type \" + serviceType + \" is not available for repository metadata rules. Available services: \" + availableServicesDescription() + \".\");\n        }","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/gradle/gradle/blob/534f27719b66953f95cc907aae7f2c1b12f5482d/platforms/software/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/AbstractArtifactRepository.java#L199-L235","documentation":"Component metadata rules declared on a repository get services injected through a tiny service registry: ObjectFactory always, plus RepositoryResourceAccessor only when the repository has a URL (something to access). If a rule requests RepositoryResourceAccessor on a URL-less repository, the lookup throws ServiceLookupException 'Can not inject RepositoryResourceAccessor since repository has no URL.'","triggerScenarios":"Declaring a repository componentMetadata / metadataSupplier rule whose action class has a RepositoryResourceAccessor parameter while the repository's URL was never set (or is set only later, after the rule is registered), then triggering resolution so the rule is instantiated.","commonSituations":"Plugins attaching metadata rules to every repository indiscriminately, including not-yet-configured ones; repositories whose URL is supplied later by environment-specific logic; local-only repositories with no remote to fetch from.","solutions":["Set the repository URL before resolution: repo.setUrl(uri('https://repo.example.com/maven')).","Register accessor-dependent rules only on repositories where url != null (guard in plugin or build logic).","Split rules: those needing remote fetch go on URL-backed repositories only; pure metadata rules drop the accessor injection."],"exampleFix":"// before\nrepositories.maven {\n    name = 'custom'\n    // no URL configured\n    componentMetadata { module('com.example:*') { all(MyRemoteFetchingRule) } } // rule injects RepositoryResourceAccessor\n}\n// after\nrepositories.maven {\n    name = 'custom'\n    setUrl('https://repo.example.com/maven')\n    componentMetadata { module('com.example:*') { all(MyRemoteFetchingRule) } }\n}","handlingStrategy":"validation","validationCode":"if (repo instanceof MavenArtifactRepository && repo.url != null) {\n    repo.componentMetadata {\n        // rules that inject RepositoryResourceAccessor\n    }\n} else {\n    logger.warn('Skipping remote-fetch metadata rule on repository without URL: ' + repo.name)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set repository URLs before registering metadata rules","In plugins, attach accessor-dependent rules only when url != null","Keep remote-fetching rules and pure metadata rules separate"],"tags":["gradle","repositories","metadata-rules","service-injection","url"],"backgroundTag":"service-injection-unavailable","analyzedSha":"534f27719b66953f95cc907aae7f2c1b12f5482d","analyzedAt":"2026-08-22T08:09:12.375Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}